
//[2012.06.14.목][대폭수정!!!]{----------------------------------------------------------------
//[묶음주석] 정보 수집/처리 방식이 완전히 바뀌었다.
//<_CommentBlock_Info()> 함수 안의 설명 참고.
//
//[키:오름] 에서 처리되어 부자연 스럽던 것을 [키:내림] 에서 처리하여 자연스럽게 개선.
//[보이는 영역] 과 관련된 부분만 정보를 [수집/수정] 하므로 문서량에 무관하게 고속 편집 가능.
//
//[2012.07.03.화][참고!!!]---------------------------------------------------------------------
//
//검증시 [책갈피] 관련.
//
//[검증시] 에도 [책갈피] 기능은 동작하고 또 필요하므로 [검증시] 에 <*.bk> 문서를 저장한다.
//원래는 [검증시] 에는 <*.bk> 문서 저장을 하지 않으려 했으나 필요성이 있어 그대로 둔다.
//현재 검증시작 문서가 [책갈피] 설정이 이미 존재하는 경우 [검증시] 라고 <*.bk> 문서로 저장하지
//않는 경우는 현재 설정된 것을 잃게 되는 문제가 있다.
//}--------------------------------------------------------------------------------------------


#include <vcl.h>                                                
#pragma hdrstop

#include "editor_edit.h"                                                              
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"                                          
Teditor_edit_Form *editor_edit_Form;
//---------------------------------------------------------------------------
                                                              
//[다른 폼]
//{                            
    #include  "c_define.h"

    #include  "main.h"
    #include  "ide_main.h"

    #include  "ide_editor.h"
    #include  "editor_top.h"
    #include  "editor_info.h"

    #include  "ide_library.h"
    #include  "gui.h"
    #include  "file.h"

    #include  "ide_buttons.h"
    #include  "gui_tabs.h"

    #include  "msg_msg.h"

    #include  "ide_msgbox.h"

    //[2009.04.25.토][추가!!!]
    #include  "debug.h"

    //[2009.04.29.수][추가!!!]
    #include  "ide_hint.h"

    //[2009.05.07.목][추가!!!]
    #include  "find_DialogBox.h"

    //[2011.07.18.월][추가!!!]
    #include  "ide_tree.h"
    #include  "tree_tree.h"

    //[2012.04.15.일][추가!!!]
    #include  "info_tree.h"

    //[2012.06.22.금][추가!!!]
    //<Get_IndexWord()> 함수를 사용하기 위한것.
    #include  "parser.h"

//}

//[클립보드 접근용]
//{
    #include  <clipbrd.hpp>

//}

__fastcall Teditor_edit_Form::Teditor_edit_Form(TComponent* Owner)
        : TForm(Owner)
{
  //[VAR]
  //{
      //[2012.09.23.일][추가!!!]
      int  color;

  //}

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

      //[2018.07.24.화][추가!!!]{---
      _isDblClick   = false;
      _isDblClicked = false;
      //}---------------------------

  //}

  //[속성]
  //{
      //[지정행 처리 관련]
      //{
          //[2010.02.16.화][추가!!!]
          //기본적으로는 사용하지 않는다.
          _focusLineNum       = -1;
          _focusLineFontColor = IDE_COLOR_1;

          //이전의 <editor_linebox> 를 대체하는 것이다.
          _focusLineBackColor = _ide_option->color_linebox;

      //}

  //}

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

      this->Color    = clWhite;

  //}

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

      //그림 영역 크기 설정.
      _bmp_->Width       = this->Width;
      _bmp_->Height      = this->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->editorBackPicturePath;

            //[확인]
            //[
                //[2007.12.04.화][추가!!!]
                //그림이 있는지 먼저 확인한다.
                if(FileExists(_bmp_path) != true)
                {
                  //그림이 존재하지 않는 경우는 기본 그림으로 대체한다.
                  _bmp_path = IDE_BACKBMP_edit_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->edit_back_brightness);
      //------------------------------------------------------------------------------
  //}

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

      _font.margin_size   = d_gutter_width + 2 - 1;

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

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

      //[한글/영문] 의 대표 [문자폭] 을 구하고 동시에 [행높이] 값도 같이 구한다.
      //이는 한번만 구해 놓으면 되는 것으로 배경을 지우기 전에 먼저 처리한다.
      _EDIT_Get_Kor_Eng_Moonja_Width();

      //[수평스크롤] 을 위한 문자폭은 [영문] 폭으로 설정한다.
      _word_width = _font_eng_width;
  //}

  //[주 저장소]
  //{
      //편집용량은 기본적으로 10M 로 설정한다.(약 30만줄이된다.)
      //[문서] 수정시에도 충분한 양이다.
      _editbuf = new char [1024*1000*10];

      _editbuf[0] = '\0';
  //}

  //[임시저장소]
  //{
      //[2007.04.09.월][추가!!!]
      //_editbuf[] 와 같은 크기로 생성한다.
      _tempbuf = new char [1024*1000*10];

      _tempbuf[0] = '\0';
  //}

  //[edit 변수]
  //{
      //[문서 기준 원점]
      //{
          _text_org_x = _font.margin_size;
          _text_org_y = 2;
      //}

      _moonja       = 0;
      _ime_TkorFeng = false;

      _caret_x = 0;
      _caret_y = 0;

      //[관리변수]
      //{
          //[입력지정자] 가 위치해야 하므로 행은 무조건 한개는 있어야 한다.
          _linecount = 1;

          //처음에는 문서가 없다. (단, '\0' 이 있으므로 1 로 설정한다.)
          _filesize = 1;

          _linestartindex = 0;
          _lineendindex   = 0;

          _linetop_linenumber = 0;
          _linetop_startindex = 0;

          _caretindex = 0;

          //[단어 구간 정보]
          //{
              //[2012.05.24.목][추가!!!]
              _wordStartIndex = 0;
              _wordEndIndex   = 0;

          //}

          //[세로줄]
          //{
              //[2012.06.08.금][추가!!!]
              _vLineEn = false;
              _vLineX  = -1;

              //[2012.06.09.토][추가!!!]
              //처음에는 항상 <true> 로 함수동작 상태로 설정.
              _sw_VLine = true;

          //}

          _row = 0;
          _col = 0;

          //[2007.04.05.목][추가!!!]
          //처음 문서는 수정되지 않은 상태이다.
          //_changed = false;
          _EDIT_Changed(true, false);

          //[2009.03.31.화][추가!!!]
          //읽기전용 속성 초기화(기본은 수정 가능한 상태).
          _readOnly = false;

          //[2009.04.25.토][추가!!!]
          //처음에는 무조건 [수정가능] 상태로 설정해야 한다.
          _readOnlyAll = false;

          //[2009.03.31.화][추가!!!]
          //기본적으로 [색동문자] 가 적용되지 않는 일반 문서로 설정한다.
          _fileKind = d_Editor_FileKind_default;

          //[문서 수정 이력 초기화]{---
          //[2009.05.03.일]
          History_Init();
          //}--------------------------

          //[문서 용도 종류]
          //{
              //[2022.06.27.월][추가]
              _fileUseKind = d_Editor_fileUseKind_Default;

          //}

      //}

      //[정지점 초기화]
      //{
          //[2007.04.13.금][추가!!!]
          _BREAKPOINT_Init(&_breakpoint);

          //[2007.04.17.화][추가!!!]
          //정지줄 색을 구한다.(테마색으로 설정하기 위한것.)
          BMP_Get_Bright_Color(IDE_COLOR_breakpoint, IDE_BRIGHT_breakline, &_breakline_color);

          //[2018.09.12.수][추가!!!]{******************************************************
          //<_BREAKPOINT_Edit_Draw()> 에서 [정지점:행] 을 <_bmp_BreakPointLine_> 을
          //한번은 그려줘야 하므로 -1 로 초기화(<_BREAKPOINT_Edit_Draw()> 함수 내부 참고).
          _breakline_color_Save = -1;
          //}******************************************************************************

      //}

      //[문서 정보 관리]
      //{
          _textinfo_count = 0;

          //처음에는 선택된 문서가 없다.(아무 문서도 열려 있지 않은 경우.)
          _textinfo_index = -1;

          //[2010.03.21.일][추가!!!]{----------------------------------------------
          //관리 가능한 총 문서수를 정의한다.
          //맨 뒤에 한개의 여분을 두어야 하므로 반드시 -1 한 개수를 사용해야 한다.
          _textMaxCount = d_TEXTINFO_max - 1;
          //}----------------------------------------------------------------------

      //}

      //기본적으로 문서는 출력되어야 한다.
      _editbuf_text_on  = true;
      _edit_caretpos_on = true;
      _edit_paste_ing   = false;
      _editbuf_text_no  = false;

      //[2012.03.27.화][추가!!!]
      _no_Editbuf_Text  = false;
      _no_Scroll_Set    = false;

      //[2009.05.07.목][추가!!!]
      _editBuf_Text_No_Select = false;;

      //[선택영역]
      //{
          //[선택영역] 을 초기화 한다.
          //둘중 하나라도 -1 인 경우는 [선택영역] 이 존재하지 않는것이다.
          //[2011.06.23.목][수정!!!]
          //전용 함수로 대체한다.
          _Select_CaretIndex(&_select_start, -1); //_select_start.caret_index = -1;
          _select_start.caret_x     = 0;
          _select_start.caret_y     = 0;

          _Select_CaretIndex(&_select_end, -1); //_select_end.caret_index   = -1;
          _select_end.caret_x       = 0;
          _select_end.caret_y       = 0;

          //기본적으로 [선택영역] 은 형성되지 않은 상태이다.
          _select_ing = false;

      //}

      //[마우스] 는 기본적으로 눌린 상태는 아니다.
      _mouse_down  = false;
      _shift_down  = false;
      _scroll_ing  = false;

  //}

  //[문서 정보 구조체 초기화]
  //{
      _TEXTINFO_Init();

  //}

  //[컨트롤 그리기]
  //{
      //컨트롤을 그려서 모양을 만든다.
      _Shape();

  //}

  //[캐럿생성]
  //{
      _caret         = new Tgui_caret_Form(this);
      _caret->Parent = this;

      //[기본설정]
      //{
          _caret->Width  = 2;
          _caret->Height = 12;
          _caret->Left   = _font.margin_size;
          _caret->Top    = 2;

      //}

      //[입력지정자] 의 기본 위치를 지정한다.
      _EDIT_CaretPos(_caret_x, _caret_y);

  //}

  //[DATABASE]
  //{
      //{DATABASE} 에 접근하기 위한 [지시자] 를 만든다.
      DATABASE_GetPtr(&_DATABASE_);

  //}

  //[간편기능목록]
  //{
      //_popup_menu_ = new Tide_popup_Form(Application);
      _popup_menu_ = new Tide_popup_Form(this);
      //전체화면을 대상으로 보여지도록 NULL 로 설정.
      _popup_menu_->Parent = NULL;

      //[초기화]
      //{
          //[2011.07.24.일][추가!!!]{-------------------------------------------
          //이전과 달리 [편집기/검증기] 의 [빠른목록] 이 구분되도록 처리한다.
          //전용 함수를 사용하여 전환하므로 이전 처리는 [주석문] 으로 처리한다.
          //}-------------------------------------------------------------------

          //[빠른목록] 을 설정한다.
          _PopupMemu_Set(true);

          /*
          //[2011.07.24.일][주석처리!!!]{----------------------------
          //위의 간단한 함수로 처리하므로 이전 것은 [주석] 처리한다.
          //}--------------------------------------------------------

          //[임시항목]
          //{
              _popup_menu_->_subitem.str[0]       = " 복사 ";
              _popup_menu_->_subitem.str[1]       = " 잘라내기 ";
              _popup_menu_->_subitem.str[2]       = " 붙이기 ";
              _popup_menu_->_subitem.str[3]       = " 삭제 ";
              _popup_menu_->_subitem.str[4]       = " 모두선택 ";

              _popup_menu_->_subitem.count        = 5;
              _popup_menu_->_subitem.select_index = -1;

          //}

          //[동작함수 등록]
          //{
              _popup_menu_->_EVENT_ItemSelect = _EVENT_PopupMenu;

          //}

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

      //}

  //}


  //[검증식 한줄 편집기]
  //{
      //[2012.09.20.목][추가!!!]{-------------------------
      //[검증식] 을 직접 입력할수있는 [한줄 편집기] 생성.
      //}-------------------------------------------------

      _dbgView_Edit          = new Tgui_edit_Form(this);
      _dbgView_Edit->Parent  = this;
      _dbgView_Edit->Visible = false;

      //[초기화]{----------------------------------------------------------------------
      _dbgView_Edit->_Width(this->Width - 13 - d_gutter_width - 5);
      _dbgView_Edit->Left = d_gutter_width - 1 + 5;
      _dbgView_Edit->Top  = this->Height/2 - _dbgView_Edit->Height/2;
      _dbgView_Edit->_EDIT_TextOut("");
      //
      //[2012.09.23.일][추가!!!]-------------------------------------------------------
      BMP_Get_Bright_Color(_ide_option->color_0, Ide_Bright_DbgView_EditBack, &color);
      _dbgView_Edit->_BackColor(color);
      //}------------------------------------------------------------------------------

      //[동작함수]
      //{
          _dbgView_Edit->_EVENT_KeyEnter    = _EVENT_KeyEnter_dbgView_Edit;

          _dbgView_Edit->_EVENT_KeyDown_Esc = _EVENT_KeyDown_Esc_dbgView_Edit;

      //}    

  //}

  
  //[검증판 초기화]
  //{
      _DEBUG_Init();

      //[2011.06.22.수][추가!!!]
      _DbgView_Init();

  //}

  //[책갈피 대화상자 위치 얻기]
  //{
      //[2012.03.01.목][추가!!!]{------------------------------------
      //부가 기능으로 [책갈피:대화상자] 위치를 여기서 한번만 얻는다.
      //}------------------------------------------------------------
      
      BookMark_DialogBox_GetPtr(&_bookMark_DialogBox);

  //}

  return;

}

__fastcall Teditor_edit_Form::~Teditor_edit_Form(void)
{
  //[2012.04.29.일][수정!!!]{---------------
  //안전을 위하여 선언한 역순으로 삭제한다.
  //}---------------------------------------

  if(_dbgView_bmp_AddBtn != NULL) { delete _dbgView_bmp_AddBtn; _dbgView_bmp_AddBtn = NULL; }

  if(_dbgView_bmp != NULL) { delete _dbgView_bmp; _dbgView_bmp = NULL; }

  if(_bmp_run_arrow_ != NULL) { delete _bmp_run_arrow_; _bmp_run_arrow_ = NULL; }

  //[2018.09.12.수][추가!!!]{--------------------------------------------------------------------
  if(_bmp_BreakPointLine_ != NULL) { delete _bmp_BreakPointLine_; _bmp_BreakPointLine_ = NULL; }
  //}--------------------------------------------------------------------------------------------

  if(_bmp_breakpoint_ != NULL) { delete _bmp_breakpoint_; _bmp_breakpoint_ = NULL; }

  if(_bmp_debug != NULL) { delete _bmp_debug; _bmp_debug = NULL; }


  //[2012.09.20.목][추가!!!]{-----------------------------------------------
  if(_dbgView_Edit != NULL) { delete _dbgView_Edit; _dbgView_Edit = NULL; }
  //}-----------------------------------------------------------------------


  if(_popup_menu_ != NULL) { delete _popup_menu_; _popup_menu_ = NULL; }

  if(_caret != NULL) { delete _caret; _caret = NULL; }

  if(_tempbuf != NULL) { delete [] _tempbuf; _tempbuf = NULL; }

  if(_editbuf != NULL) { delete [] _editbuf; _editbuf = NULL; }

  if(_bmp_back_ != NULL) { delete _bmp_back_; _bmp_back_ = NULL; }

  if(_bmp_ != NULL) { delete _bmp_; _bmp_ = NULL; }

}

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

void __fastcall Teditor_edit_Form::WndProc(Messages::TMessage  &Message)
{
  //[2006.12.12.화][생성!!!]{-------------------------------------------------------
  //TForm 의 경우는 바탕을 칠하고 OnPaint() 를 발생하게 되므로 실제 _Draw() 를
  //OnPaint() 에서 사용하는 경우는 크기가 변경되는 경우 바로 칠해지지 않아서
  //하얀색 바탕이 그대로 나오게 되어 보기 좋지 않게 된다.
  //따라서 TForm 자체의 바탕을 그리는 WM_ERASEBKGND 에서 바로 _Draw() 를 사용하여
  //그리고 OnPaint() 는 처리하지 않는다.
  //C++Builder 와 같이 완벽하게 처리되는 깜박임이 전혀 없는 화면을 만들수 있다.
  //
  //[2009.05.08.금][수정!!!]--------------------------------------------------------
  //이전과 달리 그냥 return 하지 않고 "Message.Result = true;" 를 먼저 처리한다.
  //
  //[2012.05.28.월][중요수정!!!]
  //<Ctrl+F9>, <Alt+F9>, <Ctrl+Space> 의 경우는 [검증시] 에는 동작되지 않아야 한다.
  //[버튼] 으로 동작되는 것은 사전에 차단되지만 [단축키] 는 금일 추가했다.
  //
  //[2012.06.09.토][중요수정!!!]----------------------------------------------------
  //<WM_KEYUP> 에서 [묶음주석] 처리 관련.
  //
  //[2018.02.14.수][중요수정!!!]----------------------------------------------------
  //[Linux:wine] 지원 관련 중요수정 있음.
  //}-------------------------------------------------------------------------------

  //[VAR]
  //{
      bool  caret_viewalways = false;

  //}

  switch(Message.Msg)
  {                                              
    case WM_ERASEBKGND :
    {
      //[2009.05.08.금][중요참고!!!]{-------------------------------------------
      //GetClipBox() 를 사용하여 영역을 구해서 해당 영역 만큼만 BitBlt() 함수를
      //사용하는 것이 더 빠를것 같지만 실제 사용해 보니 그냥 전체를 다시 그리는
      //것리 속도가 훨씬더 빠르다.
      //따라서, 금일 수정 하려다가 이를 알고 그대로 둔다.
      //
      //[주의!!!]---------------------------------------------------------------
      //현재는 [입력지정자] 도 직접만든것인데 이 [입력지정자] 가 깜박거릴때도
      //이 곳으로 와서 다시 그려지게 된다. 처리 속도가 빨라서 그리 큰 지장이
      //없으므로 일단 그대로 둔다.
      //}-----------------------------------------------------------------------

      _Draw();

      Message.Result = true;
      return;

    } break;

    case WM_CHAR :
    {
      //[읽기전용인가?][2009.03.31.화][추가!!!]{------------------
      //[읽기전용] 인 경우는 수정하지 않는다.
      if(_readOnly == true)    { Message.Result = true; return; }
      //[2009.04.25.토][추가!!!]
      if(_readOnlyAll == true) { Message.Result = true; return; }
      //}---------------------------------------------------------

      //[<Ctrl+Space> 눌린 후처리]
      //{
          //[2012.04.15.일][추가!!!]{--------------------------------------------
          //<Ctrl+Space> 가 눌린 경우는 해당 처리부 <VK_SPACE> 에서 처리후
          //다시 문자 입력부인 이곳으로 온다.
          //따라서, <Ctrl> 이 눌려있는 경우는 이 동작으로 보고 [공백입력] 을
          //처리하지 않는다.
          //
          //<Ctrl+'F'> 등 다른 조함은 이 문제가 발생하지 않는데 [공백] 의 경우는
          //이곳으로 온다.
          //현재 원인은 알수 없으나 안전하게 처리해 놓는다.
          //}--------------------------------------------------------------------

          if     ((bool)GetAsyncKeyState(VK_CONTROL) == true)
          {
            Message.Result = true; return;

          }
          else if((info_tree_Form->_hideByKey == true) && (Message.WParam == VK_SPACE))
          {
            //[2012.05.14.월][추가!!!]{--------------------------------------------
            //<Ctrl+Space> 왁 같은 이유이다.
            //<infoTree> 가 보이는 상태에서 <Space> 가 눌린 경우는 <infoTree> 에서
            //[선택항목] 을 현재 [입력지정자] 단어로 덮어쓰게 된다.
            //<InfoTree_Key_Space()> 함수 설명 참고.
            //}--------------------------------------------------------------------

            //[중요!!!]{----------------------------------------------------------------
            //계속 <키:Space> 가 동작되지 않는 것을 막기 위하여 반드시 <false> 로 처리.
            info_tree_Form->_hideByKey = false;
            //}-------------------------------------------------------------------------

            Message.Result = true; return;

          }

      //}

      //[영문] 인 경우만 처리한다.
      if(_ime_TkorFeng == false)
      {
        _moonja = (Message.WParam & 0xff);

        //0x20 ~ 0x7e 까지만 눈에 보이는 문자이므로 이 범위의 문자만 처리한다.
        if((0x20 <= _moonja) && (_moonja <= 0x7e))
        {
          //[문자출력]{------------------------
          _CARET_MOONJA_Insert(_moonja, true);
          //}----------------------------------

          //[문서수정]{-----------------
          //[2007.03.목][추가!!!]
          //문서가 수정됐음을 기록한다.
          _EDIT_Changed(false, true);
          //}---------------------------

        }

      }

      Message.Result = true;
      return;

    } break;

    case WM_IME_STARTCOMPOSITION :
    {
      _ime_TkorFeng = true;

      Message.Result = true;
      return;
      
    } break;

    case WM_IME_COMPOSITION :  
    {
      //[읽기전용인가?][2009.03.31.화][추가!!!]{------------------
      //[읽기전용] 인 경우는 수정하지 않는다.
      if(_readOnly == true)    { Message.Result = true; return; }
      //[2009.04.25.토][추가!!!]
      if(_readOnlyAll == true) { Message.Result = true; return; }
      //}---------------------------------------------------------

      //[!]{----------------------------------------------------------------
      //실제 WM_IME_COMPOSITION 에서 한글의 조합을 알수 있고 처리할수 있다.
      //실제로 문자를 얻을수 있는 부분이다.
      //}-------------------------------------------------------------------

      //[현재 상태 알기]
      //{
          if     (Message.LParam & GCS_RESULTSTR)
          {
            //[완성된상태][2018.02.21.수][수정!!!]{-----------------------------------
            //완성된 문자는 <_moonja[]>, <_imeBuffer[]> 에 2바이트 값으로 들어 있으나
            //<_imeBuffer[]> 는 [윈도우/Linux:wine] 모두 사용 가능 하고
            //<_moonja[]> 는 [윈도우] 만 사용 가능하므로 <_imeBuffer[]> 를 사용.
            //}-----------------------------------------------------------------------

            //[한글 1 문자 출력]
            //{
                //IME 핸들 얻기.
                _imeHimc = ImmGetContext(this->Handle);

                //IME 버퍼 안의 문자수 얻기.
                _imeBufcount = ImmGetCompositionString(_imeHimc, GCS_RESULTSTR, NULL, 0);

                //저장된 문자열 얻기.
                ImmGetCompositionString(_imeHimc, GCS_RESULTSTR, _imeBuffer, _imeBufcount);

                //IME 핸들 해제.
                ImmReleaseContext(this->Handle, _imeHimc);

                _imeBuffer[_imeBufcount] = '\0';

                //[wine 지원]
                //{
                    //[2018.02.14.수][추가!!!]{-----------------------------------------------------
                    //[Linux:wine] 에서는 [한글모드] 에서 [한글/숫자/기호] 등이 전부
                    //2바이트로 넘어 온다.
                    //[Linux:UTF-8] 인 경우도 [한글] 은 [완성형한글:코드] 로 변환되어 넘어오는데
                    //이 코드값은 <_moonja(유니코드2바이트값)> 에 들어 있지 않고 <_imeBuffer[]> 에
                    //들어있다.
                    //따라서, <_imeBuffer[]> 값의 2바이트 코드를 사용해야 [Linux:wine] 에서 정상적인
                    //[한글] 을 출력할수 있다.
                    //이 경우 일반 [윈도우/Linux:wine] 모두 정확한 [한글] 출력이 된다.
                    //}------------------------------------------------------------------------------

                    //[한글] 2바이트 값 합성.
                    _moonja = ((_imeBuffer[0] << 8)&0xff00) | (_imeBuffer[1]&0x00ff);

                    //[한글] 1 문자 출력.
                    _CARET_MOONJA_Insert(_moonja, true);

                //}

            //}
            
            //[한글 조합이 기호등 문자입력으로 완성된 경우 처리]
            //{
                //[2008.02.13.수][추가!!!]{--------------------------------------------------
                //한글이 조합중일때 숫자, 기호등이 눌리면 자동으로 한글이 완성되고 눌려진
                //숫자, 기호가 뒤이어 버퍼에 저장된다.
                //이미 한글 부분은 _moonja 값으로 출력되었으므로 뒤에 붙어 있는 숫자, 기호만
                //읽어서 출력해 주면 된다.
                //IME 버퍼에 2 개가 저장돼 있다면 이미 출력된 한글 부분이므로 무시하고
                //3개 인 경우는 이 3번째 문자만 추가로 출력해주면 된다.
                //}--------------------------------------------------------------------------

                if(_imeBufcount > 2)
                {
                  //이 경우는 맨 뒤의 문자 1 개를 추가로 출력하면 된다.
                  _CARET_MOONJA_Insert(_imeBuffer[2], true);

                }

            //}

            //[문서수정]{---------------
            //[2007.03.목][추가!!!]
            //문서가 수정됐음을 기록.
            _EDIT_Changed(false, true);
            //}-------------------------

          }
          else if(Message.LParam & GCS_COMPSTR)
          {
            //[조합중인 상태]{------------------------------------------------------------
            //아직 문자가 완성되지 않고 조합중이다.
            //조함중인경우는 [입력지정자] 모양을 정사각형으로 바꾸고 여기에 출력해 준다.
            //이는 어떤 문자가 조합중인지 상태를 보여주기 위한 것이다.
            //
            //[2018.02.21.수][수정!!!]
            //<Message.WParam> 의 조합중인 문자값은 [윈도우] 에서만 정확하고 [Linux:wine]
            //에서는 [유니코드] 가 들어가서 표시에 아무 의미가 없다.
            //<_imeBuffer[]> 에는 [조합중] 인 문자가 들어 있지 않으므로 일단, [윈도우] 만
            //지원되도록 한다.
            //}---------------------------------------------------------------------------

            //[한글 문자 얻기]{-------------------------
            //현재 입력되고 있는 [한글:문자] 를 얻는다.
            _moonja = (Message.WParam & 0xffff);
            //}-----------------------------------------

            //[입력지정자 문자출력]{---------------------------------------
            //한글이 조합중인 경우는 현재 문자를 [입력지정자] 에 표시한다.
            _caret->_Shape_Composition(_moonja);
            //}------------------------------------------------------------

          }

      //}

      Message.Result = true;
      return;

    } break;

    case WM_IME_ENDCOMPOSITION :
    {
      _ime_TkorFeng = false;

      //[기본 입력지정자]{------------------------
      //다시 기본 [입력지정자] 모양으로 복구한다.
      _caret->_Shape_Default();
      //}-----------------------------------------

      Message.Result = true;
      return;

    } break;

    case WM_IME_NOTIFY :
    {
      //[!]{----------------------------------------------------------------
      //[한/영] 전환키가 눌린 경우 발생한다.
      //한번 늘릴때 마다 3 번 발생하는데 현재는 이 부분에 처리할 것은 없다.
      //}-------------------------------------------------------------------

      //[wine 안에서 구동 중인가?]
      //{
          //[2018.02.14.수][추가!!!]{-------------------------------
          //현재 wine(linux) 에서 구동 중인 경우는 처리하지 않는다.
          //}-------------------------------------------------------

          if(_ide_option->wine == true) break;

      //}

      //[한/영 전환 상태 표시]
      //{
          //[2009.04.03.금][추가!!!]{------------------------------------------------------------
          //현재 [한/영] 키가 눌릴때 마다 전환상태를 입력 지정자아래의 [상태표시자] 에 반영한다.
          //
          //[2009.04.23.목][수정!!!]-------------------------------------------------------------
          //이전에 [입력지정자] 에 생성되 있던 것을 정보판에 옮겼다.
          //}------------------------------------------------------------------------------------

          if(editor_info_Form != NULL)
          {
            if(_EDIT_IS_ImeHangul() == true) { editor_info_Form->_HanEngLabel_Han(); }
            else                             { editor_info_Form->_HanEngLabel_Eng(); }

          }

      //}

    } break;

    case WM_GETDLGCODE :
    {
      //[2006.12.21.목][중요!!!]{--------------------------------------------
      //[탭] 키와 [화살표] 키는 기본적으로 지원하지 않으므로 이 프로그램에서
      //이 키들을 사용한다는 것을 OS 에 알려주어야 사용할수 있다.
      Message.Result = DLGC_WANTARROWS | DLGC_WANTTAB;
      //[바로 종료]----------------------------------------------------------
      //반드시 여기서 종료해야 한다. 그렇지 않은 경우는 유효하지 않게 된다.
      return;
      //}--------------------------------------------------------------------


    } break;

    case WM_SETFOCUS :
    {
      //[입력지정자 보이기]
      //{
          //[!]{-------------------------------------------------
          //[입력지정자] 를 보인다.
          //
          //[2012.04.27.금][수정!!!]-----------------------------
          //[입력지정자] 를 바로 보이지 않고 [타이머:1주기] 뒤에
          //보여주는 <_Show2()> 함수를 사용.
          //}----------------------------------------------------

          _caret->_Show2();

      //}

    } break;

    case WM_KILLFOCUS :
    {
      //[입력지정자]{-----------
      //[입력지정자] 를 감춘다.
      _caret->_Hide();
      //}-----------------------

    } break;


    /*
    case WM_LBUTTONDBLCLK : //[2중눌림] 의 경우.
    {
      ShowMessage("더블클릭");

      Message.Result = true;
      return;
    } break;
    */


    case WM_KEYDOWN :
    {
      switch(Message.WParam)
      {
        case VK_INSERT :
        {
          //if     ((bool)GetAsyncKeyState(VK_SHIFT) == true)
          //[2009.05.08.금][수정!!!]
          //위의 것보다 아래 것이 더 확실하다.
          if(_shift_down == true)
          {
            //[Shift + Insert] 조합.

            //[2009.05.04.월][추가!!!]{------------------
            //BCB 와 같이 [붙이기] 하는 경우도 추가한다.
            //즉, <Ctrl + V> 와 같이 두 종류가 지원된다.
            //}------------------------------------------

            //[읽기전용인가?][2009.03.31.화][추가!!!]{------------------
            //[읽기전용] 인 경우는 수정하지 않는다.
            if(_readOnly == true)    { Message.Result = true; return; }
            //[2009.04.25.토][추가!!!]
            if(_readOnlyAll == true) { Message.Result = true; return; }
            //}---------------------------------------------------------

            //[문서수정]{-----------------
            //문서가 수정됬음을 기록한다.
            _EDIT_Changed(false, true);
            //}---------------------------

            //[2009.06.02.화][수정!!!]{----------------------------------
            //[묶음주석] 처리를 위하여 _EDIT_Changed() 와 순서를 바꾼다.
            //}----------------------------------------------------------

            _CLIPBOARD_Paste();

          }
          else if((bool)GetAsyncKeyState(VK_CONTROL) == true)
          {
            //[Conotrl + Insert] 조합.
            //...

          }
          else
          {
            //[Insert] 만 눌린 경우.

            //이전에는 [편집모드] 를 전환하는데 사용되었으나 현재는 단지 [밀어쓰기(끼워넣기)]
            //만 지원하므로 여기서는 아무 처리도 하지 않는다.

          }

          Message.Result = true;
          return;
        } break;

        //[캐럿 이동 관련]
        //{
            case VK_UP :
            {
              //[2007.04.09.월][추가!!!]{----------------------------
              //[Ctrl-Key] 가 눌린 경우는 별도 편집 처리를 수행한다.
              //}----------------------------------------------------

              if((bool)GetAsyncKeyState(VK_CONTROL) == true)
              {
                if(_shift_down == true) { Message.Result = true; return; }

                //[Ctrl + Up] 인 경우는 위로 1줄씩 [줄이동] 한다.

                //[2009.05.09.토][수정!!!]{--------------------------------------------------------------
                //원래 3줄 이동이었으나 금일 1줄 이동으로 수정한다.
                //이는 계속 이동중 [입력지정자] 가 아래로 보이지 않게 되는 경우는 자동으로 보이게 만들기
                //위하여 _KEY_Up() 함수를 사용하기 위한 것이다. 3줄이동은 별도 함수를 만들어야 하므로.
                //}--------------------------------------------------------------------------------------

                ide_editor_Form->_scroll_v_Form->_Position(ide_editor_Form->_scroll_v_Form->_position - 1);

                //[2009.05.09.토][추가!!!]{-------------------------------------------------------
                //현재 [입력지정자] 가 아래로 보이지 않는 영역에 있는지 확인만 하고 아래에 있다면
                //강제로 한행 위로 [입력지정자] 를 이동시킨다.
                if(_CARET_ViewAlways(true) == true) { _KEY_Up(true); }
                //}-------------------------------------------------------------------------------

              }
              else
              {
                //[2012.05.14.월][추가!!!]{------------------------------------
                //<infoTree> 를 감춘다.
                //<infoTree> 가 보이는 경우는 <infoTree> 함수를 우선으로 처리.
                //}------------------------------------------------------------

                if(info_tree_Form->Visible == true)
                {
                  InfoTree_Key_Up();

                }
                else
                {
                  //[입력지정자 항상 보이기]
                  //{
                      //키는 항상 눈에 보이는 위치에 있어야 한다.
                      _editbuf_text_no = true;
                      //{
                          caret_viewalways = _CARET_ViewAlways(false);
                      //}
                      _editbuf_text_no = false;
                  //}

                  _KEY_Up(caret_viewalways);

                  //[2007.03.17.토][추가!!!]{-------------------------------------------
                  //[키] 를 동작하기 전에 항상 _CARET_ViewAlways() 이 먼저 동작하는데,
                  //이때는 [키] 동작전의 행을 기준으로 동작하므로 [키] 동작후 행의
                  //길이가 이전 행의 [입력지정자] 의 위치보다 작은 경우에는 보이지 않는
                  //영역에 있을수 있다. 따라서 한번더 사용하여 확실하게 [입력지정자] 가
                  //눈에 보이는 위치에 있도록 처리해야 한다.
                  _CARET_ViewAlways(false);
                  //}-------------------------------------------------------------------

                }

              }

              Message.Result = true;
              return;
            } break;

            case VK_DOWN :
            {
              //[2007.04.09.월][추가!!!]{----------------------------
              //[Ctrl-Key] 가 눌린 경우는 별도 편집 처리를 수행한다.
              //}----------------------------------------------------

              if((bool)GetAsyncKeyState(VK_CONTROL) == true)
              {
                if(_shift_down == true) { Message.Result = true; return; }

                //[Ctrl + Down] 인 경우는 아래로 1줄씩 [줄이동] 한다.

                //[2009.05.09.토][수정!!!]{--------------------------------------------------------------
                //원래 3줄 이동이었으나 금일 1줄 이동으로 수정한다.
                //이는 계속 이동중 [입력지정자] 가 위로 보이지 않게 되는 경우는 자동으로 보이게 만들기
                //위하여 _KEY_Down() 함수를 사용하기 위한 것이다. 3줄이동은 별도 함수를 만들어야 하므로.
                //}--------------------------------------------------------------------------------------

                ide_editor_Form->_scroll_v_Form->_Position(ide_editor_Form->_scroll_v_Form->_position + 1);

                //[2009.05.09.토][추가!!!]{-----------------------------------------------------
                //현재 [입력지정자] 가 위로 보이지 않는 영역에 있는지 확인만 하고 아래에 있다면
                //강제로 한행 아래로 [입력지정자] 를 이동시킨다.
                if(_CARET_ViewAlways(true) == true) { _KEY_Down(true); }
                //}-----------------------------------------------------------------------------

              }
              else
              {
                //[2012.05.14.월][추가!!!]{------------------------------------
                //<infoTree> 를 감춘다.
                //<infoTree> 가 보이는 경우는 <infoTree> 함수를 우선으로 처리.
                //}------------------------------------------------------------

                if(info_tree_Form->Visible == true)
                {
                  InfoTree_Key_Down();

                }
                else
                {
                  //[입력지정자 항상 보이기]
                  //{
                      //키는 항상 눈에 보이는 위치에 있어야 한다.
                      _editbuf_text_no = true;
                      //{
                          caret_viewalways = _CARET_ViewAlways(false);
                      //}
                      _editbuf_text_no = false;
                  //}

                  _KEY_Down(caret_viewalways);

                  //[2007.03.17.토][추가!!!]{-------------------------------------------
                  //[키] 를 동작하기 전에 항상 _CARET_ViewAlways() 이 먼저 동작하는데,
                  //이때는 [키] 동작전의 행을 기준으로 동작하므로 [키] 동작후 행의
                  //길이가 이전 행의 [입력지정자] 의 위치보다 작은 경우에는 보이지 않는
                  //영역에 있을수 있다. 따라서 한번더 사용하여 확실하게 [입력지정자] 가
                  //눈에 보이는 위치에 있도록 처리해야 한다.
                  _CARET_ViewAlways(false);
                  //}-------------------------------------------------------------------

                }

              }

              Message.Result = true;
              return;
            } break;

            case VK_RIGHT :
            {
              //[2012.02.02.목][추가!!!]{----------------------------
              //[Ctrl-Key] 가 눌린 경우는 별도 편집 처리를 수행한다.
              //}----------------------------------------------------

              if((bool)GetAsyncKeyState(VK_CONTROL) == true)
              {
                //[2012.02.02.목][추가!!!]{------------------------------------
                //[Ctrl+Right] 인 경우는 [선택영역:오른쪽:수평이동] 으로 처리.
                //}------------------------------------------------------------

                //1개 공백 단위로 이동한다.
                _LineBlock_MoveRL_Right(1);

              }
              else
              {
                //[입력지정자 항상 보이기]
                //{
                    //키는 항상 눈에 보이는 위치에 있어야 한다.
                    _editbuf_text_no = true;
                    //{
                        caret_viewalways = _CARET_ViewAlways(false);
                    //}
                    _editbuf_text_no = false;
                //}

                //[선택영역] 처리도 수반해야 한다.
                _KEY_Right(caret_viewalways, true);

              }

              Message.Result = true;
              return;
            } break;

            case VK_LEFT :
            {
              //[2012.02.02.목][추가!!!]{----------------------------
              //[Ctrl-Key] 가 눌린 경우는 별도 편집 처리를 수행한다.
              //}----------------------------------------------------

              if((bool)GetAsyncKeyState(VK_CONTROL) == true)
              {
                //[2012.02.02.목][추가!!!]{---------------------------------
                //[Ctrl+Left] 인 경우는 [선택영역:왼쪽:수평이동] 으로 처리.
                //}---------------------------------------------------------

                //1개 공백 단위로 이동한다.
                _LineBlock_MoveRL_Left(1);

              }
              else
              {
                //[입력지정자 항상 보이기]
                //{
                    //키는 항상 눈에 보이는 위치에 있어야 한다.
                    _editbuf_text_no = true;
                    //{
                        caret_viewalways = _CARET_ViewAlways(false);
                    //}
                    _editbuf_text_no = false;
                //}

                _KEY_Left(caret_viewalways);

              }

              Message.Result = true;
              return;
            } break;

            case VK_HOME :
            {
              //[2007.04.09.월][추가!!!]{----------------------------
              //[Ctrl-Key] 가 눌린 경우는 별도 편집 처리를 수행한다.
              //}----------------------------------------------------

              if((bool)GetAsyncKeyState(VK_CONTROL) == true)
              {
                if(_shift_down == true) { Message.Result = true; return; }

                //[Ctrl + Home] 의 경우는 문서 가장 처음으로 [줄이동] 한다.

                //[209.05.08.금][수정!!!]{--------------------------------------------
                //이전같이 [줄이동] 으로 처리하지 않고 신형 함수로 간단하게 처리한다.
                History_SetCaretPos(0, true);
                //}-------------------------------------------------------------------

              }
              else
              {
                //[입력지정자 항상 보이기]
                //{
                    //키는 항상 눈에 보이는 위치에 있어야 한다.
                    _editbuf_text_no = true;
                    //{
                        caret_viewalways = _CARET_ViewAlways(false);

                    //}
                    _editbuf_text_no = false;
                //}

                _KEY_Home(caret_viewalways);

              }

              Message.Result = true;
              return;
            } break;

            case VK_END :
            {
              //[2007.04.09.월][추가!!!]{----------------------------
              //[Ctrl-Key] 가 눌린 경우는 별도 편집 처리를 수행한다.
              //}----------------------------------------------------

              if((bool)GetAsyncKeyState(VK_CONTROL) == true)
              {
                if(_shift_down == true) { Message.Result = true; return; }

                //[Ctrl + End] 의 경우는 문서 가장 끝으로 [줄이동] 한다.

                //[209.05.08.금][수정!!!]{--------------------------------------------
                //이전같이 [줄이동] 으로 처리하지 않고 신형 함수로 간단하게 처리한다.
                //제일 끝 위치에서 -1 을 해야 한다. 이 위치는 문자열 끝 위치이므로.
                History_SetCaretPos(_filesize - 1, true);
                //}-------------------------------------------------------------------

              }
              else
              {
                //[입력지정자 항상 보이기]
                //{
                    //키는 항상 눈에 보이는 위치에 있어야 한다.
                    _editbuf_text_no = true;
                    //{
                        caret_viewalways = _CARET_ViewAlways(false);

                    //}
                    _editbuf_text_no = false;
                //}

                _KEY_End(caret_viewalways);

              }

              Message.Result = true;
              return;
            } break;

            case VK_PRIOR : //[PageUp]
            {
              //[입력지정자 항상 보이기]
              //{
                  //키는 항상 눈에 보이는 위치에 있어야 한다.
                  _editbuf_text_no = true;
                  //{
                      caret_viewalways = _CARET_ViewAlways(false);

                  //}
                  _editbuf_text_no = false;
              //}

              _KEY_PageUp();

              //[2007.03.17.토][추가!!!]{-------------------------------------------
              //[키] 를 동작하기 전에 항상 _CARET_ViewAlways() 이 먼저 동작하는데,
              //이때는 [키] 동작전의 행을 기준으로 동작하므로 [키] 동작후 행의
              //길이가 이전 행의 [입력지정자] 의 위치보다 작은 경우에는 보이지 않는
              //영역에 있을수 있다. 따라서 한번더 사용하여 확실하게 [입력지정자] 가
              //눈에 보이는 위치에 있도록 처리해야 한다.
              _CARET_ViewAlways(false);
              //}-------------------------------------------------------------------

              Message.Result = true;
              return;
            } break;

            case VK_NEXT : //[PageDown]
            {
              //[입력지정자 항상 보이기]
              //{
                  //키는 항상 눈에 보이는 위치에 있어야 한다.
                  _editbuf_text_no = true;
                  //{
                      caret_viewalways = _CARET_ViewAlways(false);

                  //}
                  _editbuf_text_no = false;
              //}

              _KEY_PageDown();

              //[2007.03.17.토][추가!!!]{-------------------------------------------
              //[키] 를 동작하기 전에 항상 _CARET_ViewAlways() 이 먼저 동작하는데,
              //이때는 [키] 동작전의 행을 기준으로 동작하므로 [키] 동작후 행의
              //길이가 이전 행의 [입력지정자] 의 위치보다 작은 경우에는 보이지 않는
              //영역에 있을수 있다. 따라서 한번더 사용하여 확실하게 [입력지정자] 가
              //눈에 보이는 위치에 있도록 처리해야 한다.
              _CARET_ViewAlways(false);
              //}-------------------------------------------------------------------

              Message.Result = true;
              return;
            } break;

        //}

        case VK_ESCAPE : //<infoTree> 공통처리.
        {
          //[2012.05.14.월][추가!!!]{------------------------------------
          //<infoTree> 를 감춘다.
          //<infoTree> 가 보이는 경우는 <infoTree> 함수를 우선으로 처리.
          //}------------------------------------------------------------

          if((info_tree_Form->Visible == true) ||
             //[2012.06.28.목][추가!!!]
             //[귀뜸말:함수 선언 정보] 인 경우는 [실시간 선언 정보판] 이
             //감춰진 상태에서도 보일수 있으므로 [귀뜸말] 이 보이는 경우도 처리.
             (info_tree_Form->_hint->Visible == true))
          {
            InfoTree_Key_Esc();

          }

          //[검증식 한줄 편집기:감추기]
          //{
              //[2012.09.21.금][추가!!!]
              _EVENT_KeyDown_Esc_dbgView_Edit();

          //}

          Message.Result = true;
          return;

        } break;

        case VK_TAB : //Tab.
        {

          Message.Result = true;
          return;
        } break;

        case VK_RETURN : //Enter.
        {
          //[읽기전용인가?][2009.03.31.화][추가!!!]{------------------
          //[읽기전용] 인 경우는 수정하지 않는다.
          if(_readOnly == true)    { Message.Result = true; return; }
          //[2009.04.25.토][추가!!!]
          if(_readOnlyAll == true) { Message.Result = true; return; }
          //}---------------------------------------------------------

          if(info_tree_Form->Visible == true)
          {
            //[2012.05.14.월][수정!!!]{------------------------------------
            //<infoTree> 가 보이는 경우는 <infoTree> 함수를 우선으로 처리.
            //해당 함수 내부 설명 참조.
            //}------------------------------------------------------------

            InfoTree_Key_Enter();

          }
          else
          {
            _KEY_Enter(true);

            //[문서수정]{-----------------
            //[2007.03.목][추가!!!]
            //문서가 수정됬음을 기록한다.
            _EDIT_Changed(false, true);
            //}---------------------------

          }   

          Message.Result = true;
          return;
        } break;

        case VK_BACK : //Back.
        {
          //[읽기전용인가?][2009.03.31.화][추가!!!]{------------------
          //[읽기전용] 인 경우는 수정하지 않는다.
          if(_readOnly == true)    { Message.Result = true; return; }
          //[2009.04.25.토][추가!!!]
          if(_readOnlyAll == true) { Message.Result = true; return; }
          //}---------------------------------------------------------

          _KEY_Backspace();

          //[문서수정]{-----------------
          //[2007.03.목][추가!!!]
          //문서가 수정됬음을 기록한다.
          _EDIT_Changed(false, true);
          //}---------------------------

          Message.Result = true;
          return;
        } break;

        case VK_DELETE : //Del.
        {
          if     (_shift_down == true)
          {
            //<Shift + Delste> 조합.

            //[2009.05.04.월][추가!!!]{--------------------
            //BCB 와 같이 [잘라내기] 하는 경우도 추가한다.
            //즉, <Ctrl + X> 와 같이 두 종류가 지원된다.
            //}--------------------------------------------

            //[읽기전용인가?][2009.03.31.화][추가!!!]{------------------
            //[읽기전용] 인 경우는 수정하지 않는다.
            if(_readOnly == true)    { Message.Result = true; return; }
            //[2009.04.25.토][추가!!!]
            if(_readOnlyAll == true) { Message.Result = true; return; }
            //}---------------------------------------------------------

            //[문서수정]{-----------------
            //문서가 수정됬음을 기록한다.
            _EDIT_Changed(false, true);
            //}---------------------------

            //[2009.06.02.화][수정!!!]{----------------------------------
            //[묶음주석] 처리를 위하여 _EDIT_Changed() 와 순서를 바꾼다.
            //}----------------------------------------------------------

            _CLIPBOARD_Cut();

          }
          else
          {
            //기본 키 처리.

            //[읽기전용인가?][2009.03.31.화][추가!!!]{------------------
            //[읽기전용] 인 경우는 수정하지 않는다.
            if(_readOnly == true)    { Message.Result = true; return; }
            //[2009.04.25.토][추가!!!]
            if(_readOnlyAll == true) { Message.Result = true; return; }
            //}---------------------------------------------------------

            _KEY_Delete(true);

            //[문서수정]{-----------------
            //문서가 수정됬음을 기록한다.
            _EDIT_Changed(false, true);
            //}---------------------------

          }

          Message.Result = true;
          return;
        } break;

        case VK_SHIFT :
        {
          _shift_down = true;

          if(((bool)GetAsyncKeyState(VK_CONTROL) == true) && //<Ctrl-Key> 이어야 하고
             ((bool)GetAsyncKeyState(VK_MENU) != true))      //<Alt-Key>  는 아니어야 한다.
          {
            //[2009.05.04.월][추가!!!]{----------------------------
            //[되살리기] 용 단축키를 추가한다.
            //{ <Ctrl> + <Shift> } 로 BCB 와 달리 두개만 처리한다.
            //}----------------------------------------------------

            //[읽기전용인가?][2009.03.31.화][추가!!!]{------------------
            //[읽기전용] 인 경우는 수정하지 않는다.
            if(_readOnly == true)    { Message.Result = true; return; }
            //[2009.04.25.토][추가!!!]
            if(_readOnlyAll == true) { Message.Result = true; return; }
            //}---------------------------------------------------------

            //[문서수정]{-----------------
            //문서가 수정됬음을 기록한다.
            _EDIT_Changed(false, true);
            //}---------------------------

            //[2009.06.02.화][수정!!!]{----------------------------------
            //[묶음주석] 처리를 위하여 _EDIT_Changed() 와 순서를 바꾼다.
            //}----------------------------------------------------------

            //[<되살림> 하기]
            //{
                //[2009.05.04.월]{-----------------------
                //현 위치에서 [되살림] 을 한개 수행한다.
                //}--------------------------------------

                History_ReDo();

            //}

          }

          Message.Result = true;
          return;
        } break;

        case VK_F3 :
        {
          //[2009.05.07.목][추가!!!]{--------------------------------
          //현재 [찾기/교환] 대화상자의 [찾기] 동작을 계속 수행한다.
          //[교환] 은 혼란을 줄수 있으므로 여기서는 지원하지 않는다.
          //대화상자를 보여주지는 않고 동작만 수행한다.
          //}--------------------------------------------------------

          find_DialogBox_Form->_EVENT_Click_find_Btn();

          Message.Result = true;
          return;
        } break;

        case VK_F4 :
        {
          //[2019.02.14.목][추가]{-----------------------------------
          //현재 [찾기/교환] 대화상자의 [찾기] 동작을 계속 수행한다.
          //F3 와 같으나 [교환문자열] 을 찾아 준다.
          //}--------------------------------------------------------

          find_DialogBox_Form->_Find_ReplaceStr(true, true, true,
                                                //하나씩 찾는 경우는 무조건 위나 중간에 위치하게 만든다.
                                                false, true);
                                     
          Message.Result = true;
          return;
        } break;

        case VK_SPACE :
        {
          //[2012.04.15.일][추가!!!]{---------------------------------
          //<Ctrl+Space> 의 경우는 BCB 처럼 [선언정보판] 을 보여준다.
          //
          //[중요!!!]-------------------------------------------------
          //<WM_CHAR> 부분 처리 참고.
          //}---------------------------------------------------------

          //다른 <키> 와의 조합은 안되므로 오직 <Ctrl> 만 허용해야 한다.
          if(((bool)GetAsyncKeyState(VK_CONTROL) == true) && //<Ctrl-Key> 이어야 하고
             ((bool)GetAsyncKeyState(VK_SHIFT) != true) &&   //<Shift-Key> 는 아니어야 한다.
             ((bool)GetAsyncKeyState(VK_MENU) != true))      //<Alt-Key>  는 아니어야 한다.
          {

            //[검증시:동작불가]
            //{
                //[2012.05.28.월][추가!!!]{-----
                //편집상태에서만 동작해야 한다.
                //}-----------------------------

                if(ide_buttons_Form->_tabs->_tabindex > 0)
                {
                  Message.Result = true;
                  return;

                }

            //}

            //[2012.05.27.일][추가!!!]{---------------------------------------------
            //<Ctrl+Space> 가 눌린 경우 [입력지정자] 가 [보이는 영역] 밖에
            //존재하는 경우 [입력지정자] 위치를 기준으로 한 [실시간 선언 정보판] 이
            //[편집기] 를 벗어난 곳에 보일수 있으므로 이를 방지하기 위하여 항상
            //[입력지정자] 를 먼저 [편집기] 안의 [보이는 영역] 에 위치하게 만든다.
            _CARET_ViewAlways(false);
            //}---------------------------------------------------------------------

            //[2012.05.30.수][수정!!!]{----------------------------------
            //<Ctrl+Space> 로 [실시간 선언 정보판] 을 처음 보이는 경우는
            //반드시 <Parser()> 를 돌리는 전체 처리를 수행한다.
            //------------v
            InfoTree_Call(false);
            //}----------------------------------------------------------

          }
          else
          {
            if(info_tree_Form->Visible == true)
            {
              //[2012.05.14.월][수정!!!]{------------------------------------
              //<infoTree> 가 보이는 경우는 <infoTree> 함수를 우선으로 처리.
              //해당 함수 내부 설명 참조.
              //}------------------------------------------------------------

              //[읽기전용인가?]{------------------------------------------
              //[읽기전용] 인 경우는 수정하지 않는다.
              if(_readOnly == true)    { Message.Result = true; return; }
              if(_readOnlyAll == true) { Message.Result = true; return; }
              //}---------------------------------------------------------

              InfoTree_Key_Space();

            }

          }

          Message.Result = true;
          return;

        } break;

        default :
        {
          //[편집용 단축키]
          //{
              //[2007.03.22.목][추가!!!]{----------------------------------
              //[편집기] 에서 사용되는 [단축키] 를 처리한다.
              //이미 만들어져 있는 [간편기능항목] 의 함수를 빌려 사용한다.
              //}----------------------------------------------------------

              //다른 <키> 와의 조합은 안되므로 오직 <Ctrl> 만 허용해야 한다.
              if(((bool)GetAsyncKeyState(VK_CONTROL) == true) && //<Ctrl-Key> 이어야 하고
                 ((bool)GetAsyncKeyState(VK_SHIFT) != true) &&   //<Shift-Key> 는 아니어야 한다.
                 ((bool)GetAsyncKeyState(VK_MENU) != true))      //<Alt-Key>  는 아니어야 한다.
              {
                //[Ctrl + F9]
                //{
                    //[2009.05.28.목][추가!!!]{--------------------------------
                    //<Ctrl + F9> 가 눌린 경우는 BCB 처럼 <Build> 를 수행한다.
                    //}--------------------------------------------------------

                    if((Message.WParam & 0xff) == VK_F9)
                    {
                      //[검증시:동작불가]
                      //{
                          //[2012.05.28.월][추가!!!]{-----
                          //편집상태에서만 동작해야 한다.
                          //}-----------------------------

                          if(ide_buttons_Form->_tabs->_tabindex > 0)
                          {
                            Message.Result = true;
                            return;

                          }

                      //}

                      IDE_Build(d_Build_Parser|d_Build_Object|d_Build_Link|d_Build_Gvmx);

                      //다시 촛점을 [편집기] 에 맞추어 준다.
                      this->SetFocus();

                      Message.Result = true;
                      return;

                    }

                //}

                switch(Message.WParam & 0xff)
                {
                  case 'X' : case 'x' : //[잘라내기] <Ctrl + X>
                  {
                    //[읽기전용인가?][2009.03.31.화][추가!!!]{------------------
                    //[읽기전용] 인 경우는 수정하지 않는다.
                    if(_readOnly == true)    { Message.Result = true; return; }
                    //[2009.04.25.토][추가!!!]
                    if(_readOnlyAll == true) { Message.Result = true; return; }
                    //}---------------------------------------------------------

                    //[문서수정]{-----------------
                    //[2007.03.목][추가!!!]
                    //문서가 수정됬음을 기록한다.
                    _EDIT_Changed(false, true);
                    //}---------------------------

                    //[2009.06.02.화][수정!!!]{----------------------------------
                    //[묶음주석] 처리를 위하여 _EDIT_Changed() 와 순서를 바꾼다.
                    //}----------------------------------------------------------

                    _CLIPBOARD_Cut();

                  } break;

                  case 'C' : case 'c' : //[복    사] <Ctrl + C>
                  {
                    _CLIPBOARD_Copy();

                  } break;

                  case 'V' : case 'v' : //[붙 이 기] <Ctrl + V>
                  {
                    //[읽기전용인가?][2009.03.31.화][추가!!!]{------------------
                    //[읽기전용] 인 경우는 수정하지 않는다.
                    if(_readOnly == true)    { Message.Result = true; return; }
                    //[2009.04.25.토][추가!!!]
                    if(_readOnlyAll == true) { Message.Result = true; return; }
                    //}---------------------------------------------------------

                    //[문서수정]{-----------------
                    //[2007.03.목][추가!!!]
                    //문서가 수정됬음을 기록한다.
                    _EDIT_Changed(false, true);
                    //}---------------------------

                    //[2009.06.02.화][수정!!!]{----------------------------------
                    //[묶음주석] 처리를 위하여 _EDIT_Changed() 와 순서를 바꾼다.
                    //}----------------------------------------------------------

                    _CLIPBOARD_Paste();

                  } break;

                  case 'Z' : case 'z' : //[되돌리기] <Ctrl + Z>
                  {
                    //[읽기전용인가?][2009.03.31.화][추가!!!]{------------------
                    //[읽기전용] 인 경우는 수정하지 않는다.
                    if(_readOnly == true)    { Message.Result = true; return; }
                    //[2009.04.25.토][추가!!!]
                    if(_readOnlyAll == true) { Message.Result = true; return; }
                    //}---------------------------------------------------------

                    //[문서수정]{-----------------
                    //[2007.03.목][추가!!!]
                    //문서가 수정됬음을 기록한다.
                    _EDIT_Changed(false, true);
                    //}---------------------------

                    //[2009.06.02.화][수정!!!]{----------------------------------
                    //[묶음주석] 처리를 위하여 _EDIT_Changed() 와 순서를 바꾼다.
                    //}----------------------------------------------------------

                    //[<되돌림> 하기]
                    //{
                        //[2009.05.03.일]{-----------------------
                        //현 위치에서 [되돌림] 을 한개 수행한다.
                        //}--------------------------------------

                        History_UnDo();

                    //}

                  } break;

                  //[2018.02.14.수][추가!!!]
                  case 'R' : case 'r' : //[되살리기] <Ctrl + R>
                  {
                    //[읽기전용인가?][2009.03.31.화][추가!!!]{------------------
                    //[읽기전용] 인 경우는 수정하지 않는다.
                    if(_readOnly == true)    { Message.Result = true; return; }
                    //[2009.04.25.토][추가!!!]
                    if(_readOnlyAll == true) { Message.Result = true; return; }
                    //}---------------------------------------------------------

                    //[문서수정]{-----------------
                    //[2007.03.목][추가!!!]
                    //문서가 수정됬음을 기록한다.
                    _EDIT_Changed(false, true);
                    //}---------------------------

                    //[2009.06.02.화][수정!!!]{----------------------------------
                    //[묶음주석] 처리를 위하여 _EDIT_Changed() 와 순서를 바꾼다.
                    //}----------------------------------------------------------

                    //[<되돌림> 하기]
                    //{
                        //[2009.05.03.일]{-----------------------
                        //현 위치에서 [되돌림] 을 한개 수행한다.
                        //}--------------------------------------

                        History_ReDo();

                    //}

                  } break;

                  case 'F' : case 'f' : //[찾기/교환] <Ctrl + F>
                  {
                    //[2009.05.07.목][추가!!!]{--------
                    //[찾기/교환] 대화상자를 보여준다.
                    //}--------------------------------

                    //[2010.06.28.월][수정!!!]{-----------------------------------
                    //별도의 전용함수로 대체한다.
                    //이는 현재 선택된 것이 있는 경우 자동적으로 이 문자열을 찾기
                    //대화상자에 넣어 주기 위한것이다.
                    //}-----------------------------------------------------------

                    _FindDialog_Show();

                  } break;

                  case 'A' : case 'a' : //[전체선택] <Ctrl + A>
                  {
                    //[2009.05.08.금][추가!!!]{---
                    //[전체선택] 을 수행한다.
                    //}---------------------------

                    _EDIT_SelectAll();

                  } break;

                  case 'S' : case 's' : //[저장] <Ctrl + S>
                  {
                    //[2009.05.10.일][추가!!!]{---
                    //현재 문서를 저장한다.
                    //}---------------------------

                    IDE_File_Save();

                  } break;

                  //[주의!!!][2009.05.10.일]{-------------------------------
                  //열기는 단축키를 지원하면 안된다.
                  //이는 [개발검증] 시에는 문서를 열어서는 안되기 때문이다.
                  //BCB 도 열기는 단축키를 제공하지 않는다.
                  //}-------------------------------------------------------

                  case 'B' : case 'b' : //[책갈피] <Ctrl + B>
                  {
                    //[2012.02.28.화][추가!!!]{------------------
                    //[책갈피] 에 현재 [선택영역] 을 [등록] 하고
                    //[책갈피:대화상자] 를 보여준다.
                    //}------------------------------------------

                    //[책갈피] 에 등록.
                    if(_bookMark_DialogBox->_enable == true)
                    {
                      _bookMark_DialogBox->_BookMark();

                    }

                  } break;

                  case 'G' : case 'g' : //[세로줄] <Ctrl + G>
                  {
                    //[2012.06.08.금][추가!!!]{--------------------------
                    //[편집기] 에 고정 [세로줄] 을 [보이기/감추기] 한다.
                    //서로 반전 설정된다.
                    //}--------------------------------------------------

                    //[검증시:동작불가]
                    //{
                        //[2012.06.09.토][추가!!!]{-----
                        //편집상태에서만 동작해야 한다.
                        //}-----------------------------

                        if(ide_buttons_Form->_tabs->_tabindex > 0) break;

                    //}

                    //[2012.06.09.토][추가!!!]{-------------
                    //<Ctrl+G> 동작시에는 항상 세로줄 허용.
                    _sw_VLine = true;
                    //}-------------------------------------

                    if(_vLineEn == true)
                    {
                      //[2012.06.09.토][수정!!!]{-------------------------------------
                      //같은 위치인 경우만 해제시키는 경우는 [감추기] 할때
                      //다시 나온뒤 사라지게 되어 두번 처리해야 하는 번거로움이 있다.
                      //기본적으로 [한번에 한동작] 으로 처리.
                      //}-------------------------------------------------------------

                      //if(_vLineX == _caret_x)
                      //{
                      //  //같은 위치인 경우만 해제시킨다.

                        //[해제] 시킨다.
                        _vLineEn = false;

                      //}

                      //정확한 위치는 항상 입력.
                      //<_caretindexwidth> 값은 항상 <_Edit_Col()> 에서 얻어진다.
                      _vLineX = _caret_x;//_caretindexwidth;

                      //[다시 그리기] 로 반영.
                      _EditBuf_Text();

                    }
                    else
                    {
                      //[설정] 시킨다.
                      _vLineEn = true;

                      //정확한 위치는 항상 입력.
                      //<_caretindexwidth> 값은 항상 <_Edit_Col()> 에서 얻어진다.
                      _vLineX = _caret_x;//_caretindexwidth;

                      //[다시 그리기] 로 반영.
                      _EditBuf_Text();

                    }

                  } break;

                  case 'P' : case 'p' : //API 검색.
                  {
                    //[2022.07.05.화][추가]{---------------------------------
                    //<Tree:API 검색> 을 활성화 하고 API 검색 결과를 보인다.
                    //}------------------------------------------------------

                    ApiTree_Ctrl_P();

                  } break;

                }

              }
              else if(((bool)GetAsyncKeyState(VK_CONTROL) == true) && //<Ctrl-Key> 이어야 하고
                      ((bool)GetAsyncKeyState(VK_SHIFT) != true) &&   //<Shift-Key> 는 아니어야 한다.
                      ((bool)GetAsyncKeyState(VK_MENU) == true))      //<Alt-Key>  는 해당
              {
                //[Ctrl + Alt + 마우스 이동으로 탐색]
                //{
                    //[2010.08.28.토][추가!!!]{----------------------------------------
                    //현재 [편집기] 상의 [화면지정자:Y] 위치를 기록한다.
                    //
                    //[2010.09.05.일][수정!!!]-----------------------------------------
                    //<Ctrl + Alt> 로 수정한다.
                    //
                    //[2011.05.06.금][수정!!!]-----------------------------------------
                    //[줄이동 영역] 의 구별를 위하여 해당 영역에 따라 점선으로 경계를
                    //표시하게 되므로 여기서는 이를 위한 표시를 해 놓는다.
                    //}----------------------------------------------------------------

                    //현재 위치 기록.
                    _mousePosY_Ctrl = _mousePosY;

                    //[2011.05.06.금][추가!!!]
                    //[Ctrl + Alt] 가 눌렸다는 것을 알려준다.
                    //단, 중복 처리 하는 경우 <_EditBuf_Text()> 이 계속 처리되므로
                    //한번만 처리 되도록 한다.
                    if(_mouseCtrlAlt == false)
                    {
                      _mouseCtrlAlt = true;

                      //점선을 표시해 주기 위하여 다시 그린다.
                      _EditBuf_Text();

                    }

                //}

              }

          //}

          Message.Result = true;
          return;
        } break;

      }

      Message.Result = true;
      return;
    } break;

    case WM_KEYUP :
    {
      switch(Message.WParam)
      {
        case VK_SHIFT :
        {
          //[shift-key]
          //{
              //[선택영역 관련 초기화]
              //{
                  //[2007.02.10.토]{---------------------------------------------------------
                  //<shift> 가 올라온 경우는 키로 만드는 [선택영역] 생성이 끝난 것으로 본다.
                  //}------------------------------------------------------------------------

                  _select_ing = false;
                  _shift_down = false;

              //}

          //}

        } break;

        default :
        {
          //[<Ctrl + Alt> 표기 해제]
          //{
              //[2011.05.06.금][추가!!!]{------------------------------------
              //[키가 올라온] 이 시점에서 표시를 해제한다.
              //그렇지 않은 경우 [편집기] 내용을 다시 그릴때 마다 계속
              //[줄이동 영역 구분] 용 점선이 계속 그려지게 된다.
              //
              //단, 중복 처리 하는 경우 <_EditBuf_Text()> 이 계속 처리되므로
              //한번만 처리 되도록 한다.
              //}------------------------------------------------------------

              if(_mouseCtrlAlt == true)
              {
                //[중요!!!]{---------------------------------------------------------------
                //[마우스 버튼] 등의 경우도 [KEYUP] 으로 인식되므로
                //[Ctrl + Alt] 의 조합이 아직 유효한 경우는 아무것도 처리하지 않아야 한다.
                //}------------------------------------------------------------------------

                if(!(((bool)GetAsyncKeyState(VK_CONTROL) == true) && //<Ctrl-Key> 이어야 하고
                     ((bool)GetAsyncKeyState(VK_MENU) == true)))     //<Alt-Key>  는 해당
                {
                  _mouseCtrlAlt = false;

                  //점선을 해제 하기 위하여 다시 그린다.
                  _EditBuf_Text();

                }  

              }

          //}
 
        } break;

      }

      Message.Result = true;
      return;
    } break;

    case WM_SYSKEYDOWN : //[Alt] 와 결합된 시스템키 down.
    {
      //[Alt + F9]
      //{
          //[2012.05.11.금][수정!!!]{----------------------------------------------------
          //<Alt + F9> 가 눌린 경우는 현재 편집중인 문서(보이고 있는)만 [문법검사] 한다.
          //}----------------------------------------------------------------------------

          if((Message.WParam & 0xff) == VK_F9)
          {
            //[검증시:동작불가]
            //{
                //[2012.05.28.월][추가!!!]{-----
                //편집상태에서만 동작해야 한다.
                //}-----------------------------

                if(ide_buttons_Form->_tabs->_tabindex > 0)
                {
                  Message.Result = true;
                  return;

                }

            //}

            Ide_Parser_OneFile(_textinfo[_textinfo_index].filename.c_str());

            //다시 촛점을 [편집기] 에 맞추어 준다.
            this->SetFocus();

          }

      //}

      Message.Result = true;
      return;
    } break;

    case WM_SYSKEYUP : //[Alt] 와 결합된 시스템키 up.
    {

      Message.Result = true;
      return;
    } break;

  }

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

  return;

}

//------------------------------------------------------------------------------
//[함수들]----------------------------------------------------------------------
//------------------------------------------------------------------------------

void __fastcall Teditor_edit_Form::_Shape(void)
{
  //[2006.11.01.수][생성!!!]{-----------------------------------------
  //이 폼생성시에는 동적 생성되지 않는 내부 요소들이 있으므로 그릴때
  //_EditBuf_Text() 함수를 사용하지 않고 이 함수를 사용해야 한다.
  //이때만 한번 사용된다.
  //
  //[2007.03.25.일][수정!!!]------------------------------------------
  //[전체배경사용] 의 경우 한개의 배경을 사용하는 것처럽 보이게 한다.
  //}-----------------------------------------------------------------

  //[바탕색]
  //{
      //[2007.03.25.일][수정!!!]
      //배경종류에 따라 다르게 처리한다.

      if(IDE_BACKBMP_entire)
      {
        //이 경우는 한개의 그림을 여러창에서 나누어 사용해야 한다.

        if(ide_editor_Form == NULL) return;
        //[표시 시작 위치 계산]
        //{
            //크기가 변경되는 경우는 전체 바탕그림을 표시하는 시작 위치도 변경된다.
            //이는 마치 한개의 동일한 그림 위에 투명하게 위치하는 것같은 느낌을 주기 위한 것이다.
            _bmporg_x = ide_editor_Form->Left - d_border_width + 1;

            _bmporg_y = 0;
            
        //}

        //배경 그림으로 바탕을 지운다.
        BitBlt(_bmp_->Canvas->Handle, 0, 0,
               _bmp_->Width, _bmp_->Height,
               _bmp_back_->Canvas->Handle, _bmporg_x, _bmporg_y, SRCCOPY);

      }
      else
      {
        //배경 그림으로 바탕을 지운다.
        BitBlt(_bmp_->Canvas->Handle, d_gutter_width, 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);

  //}

  //[검증창]
  //{
      //[주의!!!][2007.04.10.화]
      //[전체배경] 의 경우만 사용해야 한다.
      if(IDE_BACKBMP_entire)
      {
        //_bmp_ 에 [검증창] 의 내용을 출력한다.
        _DEBUG_Draw();

      }

  //}

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

  return ;

}


void __fastcall Teditor_edit_Form::_FocusLine_Draw(void)
{
  //[2010.02.14.일][생성!!!]{--------------
  //[지정행] 인 경우는 해당 색을 칠해준다.
  //[지정행] 은 오직 한개뿐이다.
  //}--------------------------------------

  //[VAR]
  //{
      TRect  rect;

  //}

  //[영역 계산]
  //{
      //현재 행의 [사각형] 영역을 구한다.
      rect = _bmp_->Canvas->ClipRect;

      //[왼쪽 좌표]
      //{
          //왼쪽은 [검증판] 영역을 고려하여 위치를 설정한다.
          //_text_org_x 는 이미 d_Editor_GutterWidth 값이 붙임값으로 적용된 상태이다.
          if(_text_org_x > d_Editor_GutterWidth) { rect.Left = d_Editor_GutterWidth + 1; }
          else                                   { rect.Left = d_Editor_GutterWidth;     }

      //}

      //[수직 좌표]
      //{
          //수직 정보를 구한다.
          rect.Top    = _text_org_y + _focusLineNum * _line_height;
          rect.Bottom = rect.Top + _line_height;

      //}

  //}

  //[검사]
  //{
      //보이는 영역인 경우만 처리한다.
      if(!((0 <= rect.Top) && (rect.Top <= _bmp_->Height))) return;

  //}

  //[지정행 칠하기]
  //{
      //[편집기] 상의 이 행을 전부 지정색으로 칠한다.
      _bmp_->Canvas->Brush->Color = _focusLineBackColor;
      _bmp_->Canvas->FillRect(rect);

  //}

  return;

}

void __fastcall Teditor_edit_Form::_FocusLineNum(int  pLineNum)
{
  //[2010.02.14.일][생성!!!]{------------
  //[지정행] 번호를 지정한다.
  //사용되지 않는 경우는 -1 을 설정한다.
  //}------------------------------------

  //[이전행 지우기]
  //{
      //[23010.02.16.화][추가!!!]{------------------------------------------
      //먼저 이전행의 [지정행] 이 그려진 것을 지워 주어야 한다.
      //그렇지 않은 경우 계속 잔상이 남게 된다.
      //단, 아래에서 [지정행] 이 새로 지정되기 전에 먼저 처리해주어야 한다.
      //}-------------------------------------------------------------------

      //다시 행을 출력하되 [지정행] 을 그리지 않음으로써 잔상을 없엔다.
      _EditBuf_LineText(_focusLineNum, false);

  //}

  //[지정행 설정]
  //{
      _focusLineNum = pLineNum;

  //}

  //[반영]
  //{
      //다시 출력하여 즉시 반영해준다.
      //_EditBuf_Text();

      //[2010.02.16.화][수정!!!]
      //새로 만든 행출력 함수로 대체한다.
      _EditBuf_LineText(_focusLineNum, true);

  //}

}

void __fastcall Teditor_edit_Form::_EditBuf_LineText(int   pLineNumber,
                                                     //[지정행] 을 그려줄경우는 true.
                                                     bool  pFocusLineEn)
{
  //[2010.02.16.화][생성!!!]{--------------------------------------------------------------
  //지정된 행만 다시 출력한다.
  //이 함수는 [지정행(_focusLineXXX)] 을 처리시 <_EditBuf_Text()> 함수를 사용시
  //너무 많은 시간을 소모하므로 해당 행만 다시 출력해줄 함수가 필요해져 만들되
  //다른 용도로도 사용할수 있도록 범용으로 만든다.
  //
  //[2011.06.23.목][수정!!!]---------------------------------------------------------------
  //[검증식 보기판] 처리를 추가한다.
  //                
  //[참고!!!]------------------------------------------------------------------------------
  //이 함수는 이미 지정된 한개 [행] 만 처리되므로 지우는 것도 무조건 한개 [행] 만
  //처리한다. 이 함수는 이미 존재하는 문자열을 다시 출력하는 것으로 [수정] 이 아니므로
  //오직 한개 행을 다시 그려주는 것 이외의 기능은 없다.
  //
  //[주의!!!]------------------------------------------------------------------------------
  //[입력지정자] 와는 완전히 무관하므로 [입력지정자] 위치는 따지지 않는다.
  //
  //[중요!!!]------------------------------------------------------------------------------
  //이 함수는 항상 지정행이 이미 [보이고 있는 경우] 만 사용해야 정확한 결과가 나온다.
  //그렇지 않은 경우는 오류가 발생될수 있다.
  //이는 <_MOUSEDOWN_Get_LineStartIndex()> 함수를 사용하여 빠르게 해당 행의 문자열을
  //찾기 위한 것으로 자세한 내용은 <_MOUSEDOWN_Get_LineStartIndex()> 함수 설명을 참고한다.
  //}--------------------------------------------------------------------------------------

  //[VAR]
  //{
      TRect  rect;

      int    r_lineendindex;

      //처리할 행의 시작 index.
      int    lineStartIndex;

  //}

  //[출력 위치 지우기]
  //{
      //[!]{------------------
      //지정된 행만 처리한다.
      //}---------------------

      //[영역구하기]
      //{
          rect        = _bmp_->Canvas->ClipRect;
          rect.Left   = _text_org_x;
          rect.Top    = _text_org_y + pLineNumber * _line_height;
          rect.Bottom = rect.Top + _line_height;

      //}

      //[영역 검사]
      //{
          //[!]{--------------------------------------------------------------
          //보이는 영역인 경우만 처리한다.
          //실제는 항상 보이는 경우만 이 함수가 사용되나 안전장치로 마련한다.
          //}-----------------------------------------------------------------
          
          if(!((0 <= rect.Top) && (rect.Top <= _bmp_->Height))) return;

      //}

      //[출력영역지우기]
      //{
          if(IDE_BACKBMP_entire)
          {
            //이 경우는 한개의 그림을 여러창에서 나누어 사용해야 한다.

            //[표시 시작 위치 계산]
            //{
                //크기가 변경되는 경우는 전체 바탕그림을 표시하는 시작 위치도 변경된다.
                //이는 마치 한개의 동일한 그림 위에 투명하게 위치하는 것같은 느낌을 주기 위한 것이다.
                _bmporg_x = ide_editor_Form->Left - d_border_width + 1;

                _bmporg_y = 0;

            //}

            //현재 [입력지정자] 가 위치한 행만 지운다.
            //그냥 지우면 배경 그림이 지워지므로 반드시 배경 그림을 사용하여 지워야 한다.
            BitBlt(_bmp_->Canvas->Handle, rect.Left, rect.Top, rect.Right - rect.Left, _line_height,
                   _bmp_back_->Canvas->Handle, _bmporg_x + rect.Left, _bmporg_y + rect.Top, SRCCOPY);

          }
          else
          {
            //현재 [입력지정자] 가 위치한 행만 지운다.
            //그냥 지우면 배경 그림이 지워지므로 반드시 배경 그림을 사용하여 지워야 한다.
            BitBlt(_bmp_->Canvas->Handle, rect.Left, rect.Top, rect.Right - rect.Left, _line_height,
                   _bmp_back_->Canvas->Handle, rect.Left - d_gutter_width, rect.Top, SRCCOPY);

          }

      //}

  //}

  //[특별 행 처리]
  //{
      //[정지줄 처리]
      //{
          //[!]{-------------------------------------------------------------------
          //현재 행이 [정지점] 이 있는 행인 경우는 배경에 [정지줄] 을 만들어 준다.
          //}----------------------------------------------------------------------

          _BREAKPOINT_Edit_Verify_Draw(pLineNumber);

      //}

      //[지정행]
      //{
          //[2010.02.16.화][추가!!!]{--------
          //[지정행] 을 지정색으로 칠해준다.
          //단, 사용인 경우만 처리한다.
          //}--------------------------------

          if(pFocusLineEn == true)
          {
            _FocusLine_Draw();

          }
          else
          {
            //[중요!!!]{--------------------------------------------------------------------
            //[지정행] 을 사용하지 않는 경우는 아래 <_EDITBUF_LINE_Out()> 함수에서
            //[지정행] 으로 문자열이 색동문자가 적용되지 않도록 [무효 : -1] 로 지정해 준다.
            _focusLineNum = -1;
            //}-----------------------------------------------------------------------------

          }

      //}

  //}

  //[행 출력]
  //{
      //[현재행 시작 위치 구하기]
      //{
          //반드시 지정행이 이미 보이는 위치에 있어야 한다.
          _MOUSEDOWN_Get_LineStartIndex(pLineNumber, &lineStartIndex);

      //}

      //[문자열 출력]
      //{
          //x 가 적용될 절대 기준 위치를 설정해 놓는다.
          _font.margin_size = _text_org_x;

          //현재 [입력지정자] 가 위치한 행 시작부터 끝까지 해당 문자열을 다시 츨력한다.
          //행 처음부터 다시 출력해야 [문법강조] 를 수행할수 있다.
          //입력위치 x 의 _text_org_x 는 이미 _font.margin_size 에 적용된 상태이므로 따로 더할필요는 없다.
          _EDITBUF_LINE_Out(0, _text_org_y + pLineNumber * _line_height, lineStartIndex, &r_lineendindex);

      //}

      //[검증식 보기판]
      //{
          //[2011.06.23.목][추가!!!]{-------------
          //[검증식 보기판] 을 보여준다.
          //
          //[2011.06.26.일][수정!!!]--------------
          //[기본보기] 의 경우만 여기서 처리한다.
          //}-------------------------------------

          if(_dbgView_FixView == false) { _DbgView_Draw(); }

      //}

      //[검증판 반영]
      //{
          BitBlt(_bmp_->Canvas->Handle, 0, rect.Top, d_gutter_width, _line_height + 1,
                 _bmp_debug->Canvas->Handle, 0, rect.Top, SRCCOPY);

      //}

      //[검증식 보기판]
      //{
          //[2011.06.26.일][추가!!!]{-------------
          //[고정보기] 의 경우는 여기서 처리한다.
          //}-------------------------------------

          if(_dbgView_FixView == true) { _DbgView_Draw(); }

      //}

  //}

  //[수정영역 다시 그리기]
  //{
      //[!]{---------------------------------------------------------------------------------
      //_Draw() 함수를 사용하여 전체를 다시 그리지 않고 수정된 행만 다시 그려준다.
      //이는 키가 계속눌려서 문자가 계속 출력되는 경우 처리속도를 최대한 높이기 위한 것이다.
      //여기서는 무조건 처리한다.
      //}------------------------------------------------------------------------------------

      BitBlt(this->Canvas->Handle, rect.Left, rect.Top, rect.Right - rect.Left, _line_height + 1,
             _bmp_->Canvas->Handle, rect.Left, rect.Top, SRCCOPY);

  //}

  return;

}

void __fastcall Teditor_edit_Form::_EditBuf_LineTextX(//다시 그릴 시작 행 번호.
                                                      int   pStartLineNumber,
                                                      //다시 그릴 행 수.
                                                      int   pLineCount,
                                                      //[2011.06.29.수][추가!!!]
                                                      //[검증보기판] 을 보여주는 경우는 <true>.
                                                      bool  pDbgViewEn,
                                                      //[지정행] 을 그려줄경우는 true.
                                                      bool  pFocusLineEn)
{
  //[2010.02.16.화][생성!!!]{---------------------------------------------------------------
  //<_EditBuf_LineText()> 함수를 사용하여 재구성 하되, 연결된 여러개 행을 동시에 처리한다.
  //나머지는 기능이 동일하다.
  //
  //이 함수는 [검증식 보기판] 을 출력하는 경우 여러개 행에 걸쳐 출력되는데 이 경우
  //<_EditBuf_Text()> 함수를 사용시 너무 많은 시간을 소모하므로 [검증식 보기판] 이 결쳐있는
  //행만 다시 그려주기 위하여 필요하다.
  //다시 그릴때 자동으로 [검증식 보기판] 이 나타나 있다면 다시 그려주게 된다.
  //다른 용도로도 사용할수 있도록 범용으로 만든다.
  //
  //[중요!!!]-------------------------------------------------------------------------------
  //이 함수는 항상 지정행이 이미 [보이고 있는 경우] 만 사용해야 정확한 결과가 나온다.
  //그렇지 않은 경우는 오류가 발생될수 있다.
  //이는 <_MOUSEDOWN_Get_LineStartIndex()> 함수를 사용하여 빠르게 해당 행의 문자열을
  //찾기 위한 것으로 자세한 내용은 <_MOUSEDOWN_Get_LineStartIndex()> 함수 설명을 참고한다.
  //}---------------------------------------------------------------------------------------

  //[VAR]
  //{
      TRect  rect;

      int    r_lineendindex;

      //처리할 행의 시작 index.
      int    lineStartIndex;

      int    i;

  //}

  //[출력 위치 지우기]
  //{
      //[!]{-----------------------
      //지정된 행 범위만 처리한다.
      //}--------------------------

      //[영역구하기]
      //{
          rect        = _bmp_->Canvas->ClipRect;

          rect.Left   = _text_org_x;
          rect.Top    = _text_org_y + pStartLineNumber * _line_height;
          //지정 행 범위가 모두 포함된다.
          rect.Bottom = rect.Top + _line_height * pLineCount;

      //}

      //[영역 검사]
      //{
          //[!]{--------------------------------------------------------------
          //보이는 영역인 경우만 처리한다.
          //실제는 항상 보이는 경우만 이 함수가 사용되나 안전장치로 마련한다.
          //}-----------------------------------------------------------------

          if(!((0 <= rect.Top) && (rect.Top <= _bmp_->Height))) return;

      //}

      //[출력영역지우기]
      //{
          if(IDE_BACKBMP_entire)
          {
            //[!]{-----------------------------------------------------
            //이 경우는 한개의 그림을 여러창에서 나누어 사용해야 한다.
            //}--------------------------------------------------------

            //[표시 시작 위치 계산]
            //{
                //[!]{--------------------------------------------------------------------------------
                //[시작행] 부터 지정행 수만큼 해당하는 영역을 모두 지워야 한다.
                //크기가 변경되는 경우는 전체 바탕그림을 표시하는 시작 위치도 변경된다.
                //이는 마치 한개의 동일한 그림 위에 투명하게 위치하는 것같은 느낌을 주기 위한 것이다.
                //}-----------------------------------------------------------------------------------

                _bmporg_x = ide_editor_Form->Left - d_border_width + 1;

                _bmporg_y = 0;

            //}

            //[배경 지우기]
            //{
                //[2011.06.29.수][수정!!!]{--------------------------------------------------
                //[검증식 보기판] 의 [기본/고정 보기] 를 구분하여 처리한다.
                //이는 [고정보기] 인 경우는 실체 문자열이 출력되는 최고 위치가 <+2> 위치가
                //아니고 0 부터 이기 때문에 가장 위 <+2> 영역까지를 지워야 하기 때문이다.
                //그리는데는 불필요하지만, [기본보기] 로 변환되는 과정에서 [고정보기] 위치를
                //지울때 <+2> 영역에 흔적이 남는 것을 방지하기 위한 것이다.
                //}--------------------------------------------------------------------------

                if(_dbgView_FixView == true)
                {
                  //현재 [입력지정자] 가 위치한 행만 지운다.
                  //그냥 지우면 배경 그림이 지워지므로 반드시 배경 그림을 사용하여 지워야 한다.
                  //[2011.06.27.월][수정!!!]
                  //실제 문자 출력은 <+2> 위치부터 이므로 이를 보정하여 출력한다.
                  //----------------------------------------v
                  BitBlt(_bmp_->Canvas->Handle, rect.Left - 2, rect.Top - 2,
                         rect.Right - rect.Left,
                         //시작행부터 지정 행수만큼의 영역이 높이가 된다.
                         _line_height * pLineCount,
                         //[2011.06.27.월][수정!!!]
                         //실제 문자 출력은 <+2> 위치부터 이므로 이를 보정하여 출력한다.
                         //--------------------------------------------------v
                         _bmp_back_->Canvas->Handle, _bmporg_x + rect.Left - 2, _bmporg_y + rect.Top - 2, SRCCOPY);

                }
                else
                {
                  //현재 [입력지정자] 가 위치한 행만 지운다.
                  //그냥 지우면 배경 그림이 지워지므로 반드시 배경 그림을 사용하여 지워야 한다.
                  //[2011.06.27.월][수정!!!]
                  //실제 문자 출력은 <+2> 위치부터 이므로 이를 보정하여 출력한다.
                  //----------------------------------------v
                  BitBlt(_bmp_->Canvas->Handle, rect.Left - 2, rect.Top,
                         rect.Right - rect.Left,
                         //시작행부터 지정 행수만큼의 영역이 높이가 된다.
                         _line_height * pLineCount,
                         //[2011.06.27.월][수정!!!]
                         //실제 문자 출력은 <+2> 위치부터 이므로 이를 보정하여 출력한다.
                         //--------------------------------------------------v
                         _bmp_back_->Canvas->Handle, _bmporg_x + rect.Left - 2, _bmporg_y + rect.Top, SRCCOPY);

                }

            //}

          }
          else
          {
            //[!]{------------------------------------------------------------------------
            //[시작행] 부터 지정행 수만큼 해당하는 영역을 모두 지워야 한다.
            //그냥 지우면 배경 그림이 지워지므로 반드시 배경 그림을 사용하여 지워야 한다.
            //해당 영역은 이미 위에서 구했다.
            //}---------------------------------------------------------------------------

            //[2011.06.27.월][수정!!!]
            //실제 문자 출력은 <+2> 위치부터 이므로 이를 보정하여 출력한다.
            //----------------------------------------v
            BitBlt(_bmp_->Canvas->Handle, rect.Left - 2, rect.Top,
                   rect.Right - rect.Left,
                   //시작행부터 지정 행수만큼의 영역이 높이가 된다.
                   _line_height * pLineCount,
                   _bmp_back_->Canvas->Handle, rect.Left - d_gutter_width, rect.Top, SRCCOPY);

          }

      //}

  //}

  //[특별 행 처리]
  //{
      //[정지줄 처리]
      //{
          //[!]{-------------------------------------------------------------------
          //현재 행이 [정지점] 이 있는 행인 경우는 배경에 [정지줄] 을 만들어 준다.
          //지정된 행범위 전체를 대상으로 처리한다.
          //}----------------------------------------------------------------------

          for(i = pStartLineNumber; i < (pStartLineNumber + pLineCount); i++)
          {
            _BREAKPOINT_Edit_Verify_Draw(i);

          }

      //}

      //[지정행]
      //{
          //[!]{-----------------------------------------------------------------------
          //[지정행] 을 지정색으로 칠해준다.
          //[지정행] 은 별도로 관리되고 있으므로 여기서는 해당 함수를 호추하기만 한다.
          //단, 사용인 경우만 처리한다.
          //
          //[주의!!!]------------------------------------------------------------------
          //반드시 [지정행] 이 현재 처리행 범위에 들어 있는 경우만 처리해야 한다.
          //}--------------------------------------------------------------------------

          if((pStartLineNumber <= _focusLineNum) && (_focusLineNum < (pStartLineNumber + pLineCount)))
          {
            if(pFocusLineEn == true)
            {
              _FocusLine_Draw();

            }
            else
            {
              //[중요!!!]{--------------------------------------------------------------------
              //[지정행] 을 사용하지 않는 경우는 아래 <_EDITBUF_LINE_Out()> 함수에서
              //[지정행] 으로 문자열이 색동문자가 적용되지 않도록 [무효 : -1] 로 지정해 준다.
              _focusLineNum = -1;
              //}-----------------------------------------------------------------------------

            }

          }

      //}

  //}

  //[행 출력]
  //{
      //[!]{---------------------------------------
      //지정행 범위의 모든 행을 순서대로 처리한다.
      //}------------------------------------------

      for(i = pStartLineNumber; i < (pStartLineNumber + pLineCount); i++)
      {
        //[<시작행> 시작 위치 구하기]
        //{
            //반드시 지정행이 이미 보이는 위치에 있어야 한다.
            _MOUSEDOWN_Get_LineStartIndex(i, &lineStartIndex);

        //}

        //[문자열 출력]
        //{
            //x 가 적용될 절대 기준 위치를 설정해 놓는다.
            _font.margin_size = _text_org_x;

            //현재 [입력지정자] 가 위치한 행 시작부터 끝까지 해당 문자열을 다시 츨력한다.
            //행 처음부터 다시 출력해야 [문법강조] 를 수행할수 있다.
            //입력위치 x 의 _text_org_x 는 이미 _font.margin_size 에 적용된 상태이므로 따로 더할필요는 없다.
            _EDITBUF_LINE_Out(0, _text_org_y + i * _line_height, lineStartIndex, &r_lineendindex);

        //}

      }

      //[검증식 보기판]
      //{
          //[!]{-------------------------------------------------------------------
          //[검증식 보기판] 을 보여준다.
          //위에서 이미 [검증식 보기판] 이 걸치는 행만큼 모두 다시 그려 주었으므로
          //이전의 것은 지워진 상태이다.
          //여기서 전체를 다시 출력해 주면 된다.
          //
          //[2011.06.26.일][수정!!!]-----------------------------------------------
          //[기본보기] 의 경우만 여기서 처리한다.
          //}----------------------------------------------------------------------

          //[2011.06.29.수][추가!!!]
          //[검증식 보기판] 을 처리해야할 경우만 처리한다.
          if(pDbgViewEn == true)
          {
            if(_dbgView_FixView == false) { _DbgView_Draw(); }

          }

      //}

      //[검증판 반영]
      //{
          if(_dbgView_FixView == true)
          {
            //[2011.06.29.수][수정!!!]{------------------------------------------------------
            //[검증식 보기판] 이 [고정보기] 인 경우는 맨 위의 <+2> 영역을 다 채워야 한다.
            //이는 실제 [편집기] 의 문자열 출력은 <+2> 부터 시작하기 때문에 반드시 이 영역을
            //매꿔야 한다.
            //그렇지 않는 경우는 [고정=>기본 보기] 로 이동하는 경우 흔적이 남게된다.
            //}------------------------------------------------------------------------------

            //<+2> 영역 고려----------------------------v
            BitBlt(_bmp_->Canvas->Handle, 0, rect.Top - 2, d_gutter_width, _line_height*pLineCount + 1,
                   //<+2> 영역 고려--------------------------v
                   _bmp_debug->Canvas->Handle, 0, rect.Top - 2, SRCCOPY);

          }
          else
          {
            BitBlt(_bmp_->Canvas->Handle, 0, rect.Top, d_gutter_width, _line_height*pLineCount + 1,
                   _bmp_debug->Canvas->Handle, 0, rect.Top, SRCCOPY);

          }

      //}

      //[검증식 보기판]
      //{
          //[2011.06.26.일][추가!!!]{-------------
          //[고정보기] 의 경우는 여기서 처리한다.
          //}-------------------------------------

          //[2011.06.29.수][추가!!!]
          //[검증식 보기판] 을 처리해야할 경우만 처리한다.
          if(pDbgViewEn == true)
          {
            if(_dbgView_FixView == true) { _DbgView_Draw(); }

          }

      //}

  //}

  //[수정영역 다시 그리기]
  //{
      //[!]{---------------------------------------------------------------------------------
      //_Draw() 함수를 사용하여 전체를 다시 그리지 않고 수정된 행들만 다시 그려준다.
      //이는 키가 계속눌려서 문자가 계속 출력되는 경우 처리속도를 최대한 높이기 위한 것이다.
      //여기서는 무조건 처리한다.
      //단, 지정헹의 영역 만큼만 처리한다.
      //}------------------------------------------------------------------------------------

      //[2011.06.27.월][수정!!!]
      //실제 문자 출력은 <+2> 위치부터 이므로 이를 보정하여 출력한다.
      //---------------------------------------v
      BitBlt(this->Canvas->Handle, rect.Left - 2, rect.Top - 2,
             rect.Right - rect.Left,
             _line_height*pLineCount + 1,
             //[2011.06.27.월][수정!!!]
             //실제 문자 출력은 <+2> 위치부터 이므로 이를 보정하여 출력한다.
             //---------------------------------v
             _bmp_->Canvas->Handle, rect.Left - 2, rect.Top - 2, SRCCOPY);

  //}

  return;

}

void __fastcall Teditor_edit_Form::_FocusLineFontColor(int  pColor)
{
  //[2010.02.14.일][생성!!!]{------
  //[지정행] 의 문자색을 설정한다.
  //}------------------------------

  _focusLineFontColor = pColor;

  //[반영]
  //{
      //지정행이 있는 경우만 처리한다.
      if(_focusLineNum >= 0)
      {
        //다시 출력하여 즉시 반영해준다.
        //_EditBuf_Text();

        //[2010.02.16.화][수정!!!]
        //새로 만든 행출력 함수로 대체한다.
        _EditBuf_LineText(_focusLineNum, true);

      }

  //}

}

void __fastcall Teditor_edit_Form::_FocusLineBackColor(int  pColor)
{
  //[2010.02.14.일][생성!!!]{------
  //[지정행] 의 문자색을 설정한다.
  //}------------------------------

  _focusLineBackColor = pColor;

  //[반영]
  //{
      //지정행이 있는 경우만 처리한다.
      if(_focusLineNum >= 0)
      {
        //다시 출력하여 즉시 반영해준다.
        //_EditBuf_Text();

        //[2010.02.16.화][수정!!!]
        //새로 만든 행출력 함수로 대체한다.
        _EditBuf_LineText(_focusLineNum, true);

      }

  //}

}

void __fastcall Teditor_edit_Form::_Resize(void)
{
  //[2006.11.27.월][생성!!!]{--
  //크기를 조정한다.
  //}--------------------------

  //[안전장치]
  //{
      //[2012.06.05.화][추가!!!]{---------------------------------------------
      //<_bmp_> 가 [화면크기] 고정에서 [그림부품] 크기로 수시 변경되는 것으로
      //수정되었으므로 [생성] 시 크기 조정이 되는 경우 [다시 그리기] 에서
      //<ide_editor_Form> 을 참조하는 경우 오류가 발생할수 있기 때문에
      //여기서 걸러준다.
      //}---------------------------------------------------------------------

      if(ide_editor_Form == NULL) return;

  //}

  //[정보판:감추기]
  //{
      //[2012.05.23.수][추가!!!]{-----------------
      //잔상이 남지 않도록 반드시 가장 먼저 처리.
      //}-----------------------------------------

      if(info_tree_Form != NULL)
      {
        if(info_tree_Form->Visible == true) { info_tree_Form->Visible = false; }

      }

  //}

  //[검증식 한줄 편집기:감추기]
  //{
      //[2012.09.21.금][추가!!!]
      if(_dbgView_Edit != NULL)
      {
        if(_dbgView_Edit->Visible == true) { _dbgView_Edit->Visible = false; }

      }

  //}

  //[그림 부품 크기 조정]
  //{
      this->Width  = this->Parent->Width - this->Left;
      this->Height = this->Parent->Height - this->Top;

  //}

  //[<_bmp_> 크기 조정]
  //{
      _bmp_->Width  = this->Width;
      _bmp_->Height = this->Height;

  //}

  //[<_bmp_debug> 크기 조정]
  //{
      //[2012.06.08.금][추가!!!]{------------
      //[크기 조정] 후 반드시 다시 그려준다.
      //}------------------------------------

      _bmp_debug->Height = this->Height;

      //[다시 그리기]
      //{
          _DEBUG_Shape();
          //_DEBUG_Draw() 는 아래의 <_EditBuf_Text()> 내부에서 자동 반영된다.

      //}

  //}

  //[묶음주석 정보 수집]
  //{
      //[2012.06.13.수][추가!!!]{---------------------------------------------
      //[크기 조정] 시에도 [편집기:보이는 영역] 이 변경되고
      //[묶음주석] 부분이 안보이다 보일수 있으므로 반드시
      //[묶음주석] 정보를 한번 수집한다.
      //
      //1) 기본적인 경우는 [보이는 처음 행] 위치가 변하지 않기 때문에
      //   부분 정보 수집으로 충분.
      //2) 이미 문서 끝이 보이는 상황에서 아래로 크기가 커지는 경우는
      //   [보이는 처음 행] 이 수정된다.
      //   그러나, 이 경우 [수직 줄이동] 이 이루어 지고 <_EDIT_V_Scroll()> 에
      //   실시간으로 [묶음주석] 정보 수집이 이루어 지므로 [전체수집] 을 할
      //   필요가 없다.
      //   [쪽] 단위 이상으로 편집기 크기가 변하는 경우는 <_EDIT_V_Scroll()>
      //   부분에서 이를 판별하여 자동으로 [전체 수집] 을 하게 된다.
      //
      //아래로 [쪽] 단위를 넘어 한번에 크기가 커지는 경우는 [부분수집] 시에도
      //항상 [보이는 영역] 아래까지 처리하기 때문에 무관.
      //따라서 항상 [부분수집] 으로 처리.
      //
      //아래에서 <_EditBuf_Text()> 로 [다시 그리기] 전에 처리.
      //}---------------------------------------------------------------------

      //부분정보 수집----v
      _CommentBlock_Info(true);

  //}

  //[전체배경사용][2007.03.25.일][추가!!!]
  //{
      //[2012.06.05.화][수정!!!]{----------------------------
      //<_bmp_> 크기가 변경되는 경우느 자동으로 다시 그린다.
      //}----------------------------------------------------

      //if(IDE_BACKBMP_entire)
      //{
        //[검증식 보기판]
        //{
            //[2011.06.27.월][추가!!!]{--------------------------------------------------------------
            //[검증식 보기판] 이 보이는 경우만 처리해야 한다.
            //단지 다시 그려주기만 하면 아래의 <_EditBuf_Text()> 에서 자동으로 [편집기] 에 반영된다.
            //}--------------------------------------------------------------------------------------

            if((_dbgView_Enable == true) && (_dbgView_Visible == true) &&
               //[2011.06.30.목][추가!!!
               //반드시 <*.c> 문서의 경우만 처리해야 한다.
               (_fileKind == d_Editor_FileKind_c))
            {
              _DbgView_Shape();

            }

        //}

        //이 경우는 다시 전체 배경 그림의 정확한 위치를 표시할수 있도록 다시 출력한다.
        //그림 위에 문자열이 있으므로 문자열을 다시 출력하면 자동으로 그림은 배경을 지우는
        //과정에서 정확한 위치가 표시된다.
        _EditBuf_Text();

      //}

  //}

  return;

}

/*
void __fastcall Teditor_edit_Form::_Resize(void)
{
  //[2006.11.27.월][생성!!!]{--
  //크기를 조정한다.
  //
  //[2012.05.23.수][수정!!!]---
  //[2012.06.05.화][수정!!!]---
  //}--------------------------

  //[안전장치]
  //{
      //[2012.06.05.화][추가!!!]{---------------------------------------------
      //<_bmp_> 가 [화면크기] 고정에서 [그림부품] 크기로 수시 변경되는 것으로
      //수정되었으므로 [생성] 시 크기 조정이 되는 경우 [다시 그리기] 에서
      //<ide_editor_Form> 을 참조하는 경우 오류가 발생할수 있기 때문에
      //여기서 걸러준다.
      //}---------------------------------------------------------------------

      if(ide_editor_Form == NULL) return;

  //}

  //[정보판:감추기]
  //{
      //[2012.05.23.수][추가!!!]{-----------------
      //잔상이 남지 않도록 반드시 가장 먼저 처리.
      //}-----------------------------------------

      if(info_tree_Form != NULL)
      {
        if(info_tree_Form->Visible == true) { info_tree_Form->Visible = false; }

      }

  //}

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

  //[전체배경사용][2007.03.25.일][추가!!!]
  //{
      if(IDE_BACKBMP_entire)
      {
        //[검증식 보기판]
        //{
            //[2011.06.27.월][추가!!!]{--------------------------------------------------------------
            //[검증식 보기판] 이 보이는 경우만 처리해야 한다.
            //단지 다시 그려주기만 하면 아래의 <_EditBuf_Text()> 에서 자동으로 [편집기] 에 반영된다.
            //}--------------------------------------------------------------------------------------

            if((_dbgView_Enable == true) && (_dbgView_Visible == true) &&
               //[2011.06.30.목][추가!!!
               //반드시 <*.c> 문서의 경우만 처리해야 한다.
               (_fileKind == d_Editor_FileKind_c))
            {
              _DbgView_Shape();

            }

        //}

        //이 경우는 다시 전체 배경 그림의 정확한 위치를 표시할수 있도록 다시 출력한다.
        //그림 위에 문자열이 있으므로 문자열을 다시 출력하면 자동으로 그림은 배경을 지우는
        //과정에서 정확한 위치가 표시된다.
        _EditBuf_Text();

      }

  //}

  return;

}
*/

void __fastcall Teditor_edit_Form::_Draw(void)
{
  //[2006.11.27.월][생성!!!]

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

  return;

}

void __fastcall Teditor_edit_Form::_EditBuf_Text(void)
{
  //[2006.11.28.화][생성!!!]{-----------------------------------
  //_editbuf[] 의 내용을 일괄 출력한다.
  //[문서원점] 은 현재 설정되 있는 값을 그대로 사용하면 된다.
  //[문서원점] 은 [스크롤] 되는 경우 자동으로 다시 계산된다.
  //
  //[2007.03.25.일][수정!!!]------------------------------------
  //[전체그림사용] 의 경우는 이 폼의 위치에 해당하는 그림영역이
  //표시 되도록 수정한다.
  //
  //[2012.03.27.화][추가!!!]------------------------------------
  //이 함수자체 유무효를 구분하여 처리.
  //[마법사:대화상자] 의 [미리보기] 기능을 지원하기 위한것.
  //
  //[2012.06.08.금][추가!!!]------------------------------------
  //[세로줄] 그리기 기능 추가.
  //}-----------------------------------------------------------

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

  //}

  //[함수 유효 확인]
  //{
      //[2012.03.27.화][추가!!!]
      if(_no_Editbuf_Text == true) return;

  //}

  //[중복출력방지]
  //{
      //[2007.01.06.토][추가!!!]------------------------------------------
      //이 경우는 아무것도 처리하지 않아야 한다.
      //이는 문서를 전환하는 경우 동시에 [수평/수직 스크롤] 이 설정되면서
      //문서가 중복 출력되어 깜박거리는 것을 방지 하기 위한 것이다.
      //}-----------------------------------------------------------------

      if(_editbuf_text_on == false) return;

  //}

  //[중복 방지]
  //{
      //[2007.03.08.목][추가!!!]{----------------------------------------------
      //[붙이기] 동작을 수행할때 [입력지정자] 를 항상 눈에 보이는 위치에 있게
      //만들어야 하는데 이때 사용되는 _CARET_ViewAlways() 함수안에서 이 함수가
      //한번 처리되므로 [붙이기] 부분에서 한번만 처리 되도록 여기서는 처리하지
      //않아야 한다.
      //}----------------------------------------------------------------------

      if(_edit_paste_ing == true) return;

  //}

  //[중복 방지]
  //{
      //[2007.03.09.금][추가!!!]
      if(_editbuf_text_no == true) return;

  //}

  //[중복 방지]
  //{
      //[2009.05.07.목][추가!!!]{-------------------------------------------------------------
      //_EDIT_CaretPos() 함수 안에서 [선택영역] 해제시 이 함수를 호출하게 되는데
      //[되돌림/되살림] 처리시나 [교체] 등에서 [선택영역] 을 많이 사용하게 되어
      //중복 처리로 인한 시간 손실이 많다.
      //따라서, 이를 위하여 이런 경우 이 함수를 동작 시키지 않도록 하기 위한 변수를 추가한다.
      //}-------------------------------------------------------------------------------------

      if(_editBuf_Text_No_Select == true) return;

  //}

  //[바탕색]
  //{
      //[2007.03.25.일][수정!!!]{--------
      //배경종류에 따라 다르게 처리한다.
      //}--------------------------------

      if(IDE_BACKBMP_entire)
      {
        //이 경우는 한개의 그림을 여러창에서 나누어 사용해야 한다.

        //[표시 시작 위치 계산]
        //{
            //[!]{----------------------------------------------------------------------
            //크기가 변경되는 경우는 [전체사용그림] 에서 이 폼의 위치에 해당하는 부분이
            //표시되도록 처리한다.
            //}-------------------------------------------------------------------------

            _bmporg_x = ide_editor_Form->Left - d_border_width + 1;

            _bmporg_y = 0;

        //}

        //배경 그림으로 바탕을 지운다.
        BitBlt(_bmp_->Canvas->Handle, 0, 0,
               _bmp_->Width, _bmp_->Height,
               _bmp_back_->Canvas->Handle, _bmporg_x, _bmporg_y, SRCCOPY);

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

      }

  //}

  //[정지줄 처리]
  //{
      //[2007.04.16.월][추가!!!]{------------------------------------------
      //[편집기] 상에 설정된 모든 [정지점] 위치에 [정지줄] 을 만들어 준다.
      //}------------------------------------------------------------------

      _BREAKPOINT_Edit_DrawAll();

  //}

  //[지정행]
  //{
      //[2010.02.16.화][추가!!!]{--------
      //[지정행] 을 지정색으로 칠해준다.
      //}--------------------------------

      _FocusLine_Draw();

  //}

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

  //}

  //[문자열]
  //{
      //[수평스크롤 적용]
      //{
          //[!]{---------------------------------------------------------------------------
          //x 출력 위치는 기본적으로 margin_size 을 기준으로 출력된다.
          //실제 출력시 사용되는 함수상의 x 좌표는 margin_size 에 대한 offset 위치가 된다.
          //}------------------------------------------------------------------------------

          _font.margin_size = _text_org_x;

      //}

      //[현재행 시작 위치 구하기]
      //{
          //[2007.02.20.화][추가!!!]{-----------------------------------------------------
          //[선택영역]이 해제되는 경우 [입력지정자] 위치가 바뀌에 되어 _caretindex 값도
          //수정되므로 [입력지정자] 가 위치한 행의 시작 index 도 다시 계산해 주어야 한다.
          //}-----------------------------------------------------------------------------

          STR_Get_ThisLineStartIndex(_editbuf, _caretindex, &_linestartindex);
          
      //}

      //새로 적용하는 함수.
      _EDITBUF_STRING_Out(0, _text_org_y, _linetop_startindex);

  //}

  //[줄이동 영역 구분 점선 표시]
  //{
      //[2011.05.06.금][추가!!!]{--------------------------------------------------------------
      //[Ctrl + Alt] 를 누르는 경우 [마우스 줄이동 영역] 을 위한 [점선] 을 표시해 주어야 한다.
      //다른 모든 처리가 끝난뒤 가장 마지막으로 처리해 주어야 된다.
      //<_mouseCtrlAlt : true> 인 경우는 무조건 처리해 준다.
      //전용 처리 함수를 사용한다.
      //}--------------------------------------------------------------------------------------

      if(_mouseCtrlAlt == true) { _CtrlAltMouse_ScrollAreaDotLine(); }

  //}

  //[세로줄]
  //{
      //[2012.06.08.금][추가!!!]{---------------------------------------------
      //[2012.06.09.토][수정!!!]----------------------------------------------
      //여기서는 [세로줄] 을 그리지 않는다.
      //<_EDITBUF_STRING_Out()> 와 <_EDITBUF_LINE_Out()> 함수에서만 그려진다.
      //이 함수 자체로도 바로 위의 <_EDITBUF_STRING_Out()> 를 사용하기 때문에
      //여기서는 처리할 필요가 없다.
      //}---------------------------------------------------------------------

      //[2012.06.09.토][주석처리!!!]
      //if(_vLineEn == true) { _VLine(); }

  //}

  //[검증식 보기판]
  //{
      //[2011.06.26.일][수정!!!]{-------------
      //[기본보기] 의 경우만 여기서 처리한다.
      //}-------------------------------------

      if(_dbgView_FixView == false) { _DbgView_Draw(); }

  //}

  //[검증창 그리기]
  //{
      //[2007.04.08.일][추가!!!]
      //_bmp_ 에 [검증창] 의 내용을 력한다.
      _DEBUG_Draw();

  //}

  //[검증식 보기판]
  //{
      //[2011.06.26.일][추가!!!]{-------------
      //[고정보기] 의 경우는 여기서 처리한다.
      //}-------------------------------------

      if(_dbgView_FixView == true) { _DbgView_Draw(); }

  //}

  //[표시하기]
  //{
      _Draw();

  //}

  return;

}

void __fastcall Teditor_edit_Form::_Scroll_Set(void)
{
  //[2007.01.03.수][생성!!!]{----------------------------------------------------
  //_Scroll_Resize() 함수와 완전히 같은 함수이나, _Scroll_Resize() 함수와 달리
  //[문서] 를 처음 여는 경우 완전히 [스크롤] 을 새로 설정한다.
  //이는, 이전 문서로 인하여 이미 [스크롤] 되 있는 경우 처음 여는 [문서] 가
  //제 위치에 출력 되지 않기 때문에, [문서] 를 처음 여는 경우는 이를 무시하고
  //항상 문서원점 (0, 0) 위치에 출력하기 위한것이다.
  //따라서, [스크롤] 의 _min, _max, _position, _design_size 을 전부 재 설정한다.
  //[수평/수직] 모두 다 초기화 해 주어야 한다.
  //
  //[2012.03.27.화][추가!!!]-----------------------------------------------------
  //이 함수자체 유무효를 구분하여 처리.
  //[마법사:대화상자] 의 [미리보기] 기능을 지원하기 위한것.
  //}----------------------------------------------------------------------------

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

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

  //[함수 유효 확인]
  //{
      //[2012.03.27.화][추가!!!]
      if(_no_Scroll_Set == true) return;

  //}

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

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

      //전체 문서 행수는 이미 구해 놓은 전역변수값을 사용한다.
      //스크롤 되는 문서의 행수를 구한다.
      scroll_line = _linecount - view_line;

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

      }
  //}

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

      //문서를 처음 여는 것이므로 완전히 위치를 초기화 한다.

      ((Tide_editor_Form *)(this->Parent))->_scroll_v_Form->_min = 0;

      //현재 보이는 영역의 행수.
      //[2012.06.12.화][설명!!!]
      //<_linecount> 는 [전체행수] 다.
      ((Tide_editor_Form *)(this->Parent))->_scroll_v_Form->_design_size = _linecount / 4;

      //스크롤 될 문서의 총 행수.
      ((Tide_editor_Form *)(this->Parent))->_scroll_v_Form->_max = scroll_line;

      //처음 문서를 여는 것이므로 위치도 0 으로 초기화 한다.
      ((Tide_editor_Form *)(this->Parent))->_scroll_v_Form->_Position(0);

  //}

  //[수평 스크롤바 설정]
  //{
      if(((Tide_editor_Form *)(this->Parent))->_scroll_h_Form == NULL) return;

      //수평의 경우는 문서량에는 무관하므로 위치만 초기화 하면 된다.
      ((Tide_editor_Form *)(this->Parent))->_scroll_h_Form->_Position(0);

  //}

  return;

}

void __fastcall Teditor_edit_Form::_Scroll_Resize(void)
{
  //[2006.11.29.수][생성!!!]{---------------------------------------------------------
  //문서량에 따라 scrollbar 를 재설정한다.
  //단, 현재 보이는 영역의 문서는 스크롤 대상이 아니므로 제외 한다.
  //[2006.12.28.목][수정!!!]{---------------------------------------------------------
  //[편집기] 의 경우는 10만줄 정도의 양이 될수 있는데 이때 STR_Get_LineCount()
  //함수로 행수를 구하는 것은 시간이 많이 소요될수 있으므로 이미 구해놓은 행수를
  //사용하여 처리 시간을 줄인다.
  //_Scroll_Resize() 함수는 [폼] 의 크기가 변경되는 경우 계속 호출 되므로 처리 시간을
  //단축하는 것이 좋다.
  //}---------------------------------------------------------------------------------

  //[주의!!!]
  //{
      //-----------------------------------------------
      //이 함수는 _design_size, _max 만 새로 정의한다.
      //이미 연 문서간의 전환시 사용되는 함수이다.
      //-----------------------------------------------
  //}

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

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

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

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

      //전체 문서 행수는 이미 구해 놓은 전역변수값을 사용한다.
      //스크롤 되는 문서의 행수를 구한다.
      scroll_line = _linecount - view_line;

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

      }
  //}

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

      //현재 보이는 영역의 행수.
      ((Tide_editor_Form *)(this->Parent))->_scroll_v_Form->_design_size = _linecount / 4;

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

  return ;

}

bool __fastcall Teditor_edit_Form::_EditFile_SetKind(char  *pFileName)
{
  //[2009.05.28.목][생성!!!]{---------------------------------------------------
  //현재 문서의 확장자를 구분하여 문서 종류를 구분하고 해당 설정을 한다.
  //관리 종류에 해당하는 경우는 true 를 반환한다.
  //이는 [새문서] 를 <*.c> 등 [색동문자] 가 적용되는 문서로 저장하는 경우는
  //저장하면서 동시에 이 [색동문자] 를 적용해 주어야 하기 때문이다.
  //
  //[열기/저장] 대화상자를 보여주는 상황이라면 새로 문서를 설정해 주어야 하므로
  //반드시 이 함수를 호출하여 문서의 성격을 구분해 주어야 한다.
  //
  //[주의!!!]-------------------------------------------------------------------
  //[저장] 의 경우는 반드시 [새문서] 를 저장하는 경우만 해당된다.
  //현재는 [다른이름으로 저장] 의 경우는 현재 문서는 그대로 있으며 문서만 새로
  //지정 폴더에 복사 생성되는 것으로, 이 문서가 열리는 것이 아니므로 처리하지
  //않아야 한다. 오직, 현재 열려 있는 문서에 대한 경우만 처리되어야 한다.
  //
  //[2011.06.03.금][수정!!!]----------------------------------------------------
  //<*.gob1> 도 <OBJ> 관련 문서로 취급하여 같은 [색동문자] 를 적용한다.
  //}---------------------------------------------------------------------------

  //[VAR]
  //{
      //전달받은 [문서이름] 에서 추출한 [확장자] 를 가진다.
      char  fileExt[OPT_wordStrSize];

  //}

  //[문서 종류 확인]
  //{
      //[2009.04.01.수][중요추가!!!]{----------------------------------------------------
      //특별처리 문서는 해당 문서에 따라서 별도의 속성을 부여한다.
      //단, 속성을 설정해 주어야 하므로 _ROOT_TEXTINFO_Init() 함수 처리 다음에 처리한다.
      //
      //<*.c   > = [수정가능] && [문서종류 : c   ]
      //<*.gasm> = [수정불가] && [문서종류 : gasm]
      //<*.gcsm> = [수정불가] && [문서종류 : gcsm]
      //[2009.05.28.목][추가!!!]
      //<*.gtxt> = [수정가능] && [문서종류 : gtxt]
      //
      //[2011.05.27.금][추가!!!]---------------------------------------------------------
      //<*.gobj>/<*.glib> = [수정불가] && [문서종류 : obj]
      //
      //[2011.06.03.금][추가!!!]---------------------------------------------------------
      //<*.gob1> = [수정불가] && [문서종류 : obj]
      //
      //[2011.06.06.월][추가!!!]---------------------------------------------------------
      //<*.gtmp> = [수정불가] && [문서종류 : gtmp]
      //}--------------------------------------------------------------------------------

      //[확장자 구하기]
      //{
          STR_GetFileExt(pFileName, fileExt);

      //}

      //확장자 비교는 [대/소] 문자를 구분하지 않고 비교해야 한다.
      if     (STR_Match_NoCase(fileExt, "c") ||
              STR_Match_NoCase(fileExt, "h") ||
              //[2011.12.06.화][추가!!!]
              STR_Match_NoCase(fileExt, "cpp"))
      {
        //<*.c> 문서인 경우.
        _readOnly = false;
        _fileKind = d_Editor_FileKind_c;

        //[문서 수정 이력 초기화]{---
        //[2009.05.03.일]
        History_Init();
        //}--------------------------

        //[<묶음주석> 정보 얻기][2009.06.03.수][추가!!!]{---------------------
        //문서를 열때 한번은 무조건 [묶음주석] 정보정리를 수행해 주어야 한다.
        //
        //[2012.06.12.화][수정!!!]--------------------------------------------
        //문서를 열때 는 문서 처음부터 정보 수집.
        //-----------------v
        _CommentBlock_Info(false);
        //}-------------------------------------------------------------------

        return(true);

      }
      else if(STR_Match_NoCase(fileExt, "gasm") ==  true)
      {
        //<*.gasm> 문서인 경우.
        _readOnly = true;
        _fileKind = d_Editor_FileKind_gasm;

        return(true);

      }
      else if(STR_Match_NoCase(fileExt, "gcsm") ==  true)
      {
        //<*.gcsm> 문서인 경우.
        _readOnly = true;
        _fileKind = d_Editor_FileKind_gcsm;

        //[<묶음주석> 정보 얻기][2009.06.03.수][추가!!!]{---------------------
        //문서를 열때 한번은 무조건 [묶음주석] 정보정리를 수행해 주어야 한다.
        //
        //[2012.06.12.화][수정!!!]--------------------------------------------
        //문서를 열때 는 문서 처음부터 정보 수집.
        //-----------------v
        _CommentBlock_Info(false);
        //}-------------------------------------------------------------------

        return(true);

      }
      else if(STR_Match_NoCase(fileExt, "gtxt") ==  true)
      {
        //[2009.05.28.목][추가!!!]{----
        //<*.gtxt> 인 경우를 처리한다.
        //}----------------------------

        //<*.gtxt> 문서인 경우.
        _readOnly = false;
        _fileKind = d_Editor_FileKind_gtxt;

        //[문서 수정 이력 초기화]{---
        History_Init();
        //}--------------------------

        //[<묶음주석> 정보 얻기][2009.06.03.수][추가!!!]{---------------------
        //문서를 열때 한번은 무조건 [묶음주석] 정보정리를 수행해 주어야 한다.
        //
        //[2012.06.12.화][수정!!!]--------------------------------------------
        //문서를 열때 는 문서 처음부터 정보 수집.
        //-----------------v
        _CommentBlock_Info(false);
        //}-------------------------------------------------------------------

        return(true);

      }
      else if((STR_Match_NoCase(fileExt, "gobj") ==  true) ||
              (STR_Match_NoCase(fileExt, "glib") ==  true) ||
              //[2011.06.03.금][추가!!!]
              //<*.gobj> 와 <*.gob1> 은 같은 계열이므로 이것도 넣는다.
              (STR_Match_NoCase(fileExt, "gob1") ==  true))
      {
        //[2011.05.27.금][추가!!!]{-------
        //<*.gobj>, <*.glib> 문서인 경우.
        //}-------------------------------
        _readOnly = true;
        _fileKind = d_Editor_FileKind_obj;

        return(true);

      }
      else if(STR_Match_NoCase(fileExt, "gtmp") ==  true)
      {
        //[2011.06.06.월][추가!!!]{---
        //<*.gtmp> 문서인 경우.
        //}---------------------------
        _readOnly = true;
        _fileKind = d_Editor_FileKind_gtmp;

        return(true);

      }
      else
      {
        //일반 문서의 경우.
        _readOnly = false;
        _fileKind = d_Editor_FileKind_default;

        //[문서 수정 이력 초기화]{---
        //[2009.05.03.일]
        History_Init();
        //}--------------------------

        return(true);

      }

  //}

  //여기까지 온것은 해당하지 않는 것이다.
  return(false);


}

void __fastcall Teditor_edit_Form::_EDITFILE_Open(AnsiString  pFILEname)
{
  //[2006.12.16.토][생성!!!]{-------------------------------------------------------
  //지정된 [문서] 를 읽어서 _editbuf[] 에 넣어 준다.
  //이전에 _editbuf[] 안의 내용은 완전히 무시한다.
  //문서를 다시 표시하고 스크롤정보등도 이에 맞게 다시 수정하며 [편집기] 에
  //보여주는 것까지 완전히 처리한다.
  //
  //[2006.12.28.목][추가!!!]--------------------------------------------------------
  //[문서] 를 열어주는 시점에서 [문서] 총 행수를 구하여 전역변수에 저장한다.
  //
  //[2007.01.04.목][수정!!!]--------------------------------------------------------
  //문서를 처음 여는 경우만 사용하므로 기본 정보도 역시 전부 초기화 해 주어야 한다.
  //
  //[2007.01.10.수][수정!!!]--------------------------------------------------------
  //연 문서의 byte 단위 크기를 반드시 기록해 놓는다.
  //
  //[2007.03.23.금][수정!!!]--------------------------------------------------------
  //[문서] 를 열면서 자동으로 복제 [임시문서] 를 생성하여 저장한다.
  //이는 사용자가 직접 저장하기 전까지는 원본을 손상시키지 않기 위한 것이다.
  //문서전환시 이전에 수정한 문서를 자동으로 저장하게 되는데, 이때 이 [임시문서] 를
  //사용하여 처리하게 되고 새로 전환시 여는 문서도 바로 [임시문서] 가 된다.
  //즉, [문서] 는 오로지 사용자가 직접 저장하는 경우만 실제 수정된 내용이 저장된다.
  //
  //[2007.03.29.목][수정!!!]--------------------------------------------------------
  //[문서이름] 이 "새문서.XXX" 인 경우는 [새문서] 이므로 전용 지정 폴더위치의
  //[문서이름] 으로 변환하여 사용해야 한다.
  //
  //[2009.04.01.수][중요수정!!!]----------------------------------------------------
  //[문서] 를 열때 [확장자] 에 따라서 편집속성을 달리해 주어야 한다.
  //특별 처리 대상이 되는 문서는 아래와 같다.
  //<*.c>, <*.gasm>, <*.gcsm> 3개 종류가 된다.
  //
  //[2012.03.01.목][추가!!!]--------------------------------------------------------
  //[현재 여는 문서] 와 같은 위치에 해당 [책갈피 문서] 가 있다면 [책갈피] 에 설정.
  //
  //[2019.03.08.금][중요수정]*******************************************************
  //[CRLF:완성] 처리부 추가.
  //}-------------------------------------------------------------------------------

  //[VAR]
  //{
      //[2007.03.23.금][추가!!1]
      //pFILEname 의 복제 [임시문서이름] 을 저장한다.
      AnsiString   tempfilename = "";

      //[2007.03.29.목][추가!!!]
      //임시 파일이 존재할 path 를 미리 만들어 놓는다.
      //무조건 *.exe 의 [temp] 폴더에 저장된다.
      AnsiString   newfilepath = ExtractFilePath(Application->ExeName) + "temp\\";

      //"새문서" 인지 확인만 하므로 '\0' 까지 7 byte 면 충분하다.
      char         word[7];

      //[2009.04.01.수][추가!!!]
      //현재 문서의 [확장자] 만 추출한다.
      char         fileExtStr[OPT_wordStrSize];

      //[2019.03.08.금][추가/정리]
      //{
          AnsiString   fileName = "";

          char        *fileBuf  = NULL;

          int          fileSize = 0;

      //}
      
  //}

  //["새문서" 인가?]
  //{
      //[2007.03.29.목][추가!!!]{------------------------------------------------
      //[새문서] 인 경우는 전용 공간에 [문서] 가 존재하므로 이곳에서 해당 이름의
      //문서를 찾아서 열어 주어야 한다.
      //처음 6 byte 만 읽어서 저장하면 쉽게 확인할수 있다.
      memmove(word, pFILEname.c_str(), 6);
      //}------------------------------------------------------------------------

      //문자열로 만든다.
      word[6] = '\0';

      //"새문서" 라면 실제 [문서이름] 으로 완성해 준다.
      if(STR_Match(word, "새문서") == true)
      {
        //[새문서] 의 전체 [문서이름] 을 만들어 준다.
        fileName = newfilepath + pFILEname;

      }
      else
      {
        //전달된 이름을 그대로 사용한다.
        fileName = pFILEname;

      }

  //}

  //[문서 열기]
  //{
      //[2019.03.08.금][추가]{-----------------------------------
      //[문서] 에 [CR/LF] 등 [CRLF] 가 아닌 경우 [CRLF] 로 교체.
      //이는 [Linux:Wine] 지원을 위하여 절대적으로 필요.
      //전용 처리 함수로 처리.
      //}--------------------------------------------------------

      //문서 열기(내부적으로 저장소 자동 생성).
      FILE_Open(fileName, (unsigned char **)(&fileBuf), &fileSize);

      //CRLF 완성 처리(fileBuf(주소), fileSize(크기) 는 내부적으로 수정된것).
      Str_CRLF_Complete(&fileBuf, &fileSize);

      //[정확한 파일 크기 처리]
      //{
          //[2021.01.15.금][중요수정]{********************************************
          //복잡한 편집후 <_filesize> 의 약간의 차이가 발생하는 문제가 있다.
          //이때문에, 저장시 '\0' 다음에 약간의 문자열이 뒤에 덧붙여 저장되어
          //이 파일을 다시 읽어들일때 '\0' 다음의 문자열까지 읽혀지고, 편집기에는
          //보이지 않지만 [문법검사] 시 오류가 발생할수 있는 원인이 된다.
          //
          //[해결]****************************************************************
          //
          //<_filesize> 정보를 보정하는 의미로, [열기] 와 [저장] 시에는 반드시
          //<STR_Assign()>, STR_Length() 로 각각 정확한 문자열의 길이를 사용하여
          //처리한다.
          //즉, 이 두 함수로 구해진 정확한 문자열 길이를 <_filesize> 에 할당하여
          //정확한 보정을 한다.
          //}*********************************************************************

          //[편집기] 저장소에 저장.
          //'\0' 크기 포함----------------------------v
          _filesize = STR_Assign(_editbuf, fileBuf) + 1;

          //[이전코드]
          //{
              //[2021.01.15.금][주석처리]
              /*
              //[편집기] 저장소에 저장.
              STR_Assign(_editbuf, fileBuf);

              //현재 [문서크기] 기록.
              _filesize = fileSize;
              */

          //}   

      //}    

      //반드시 여기서 생성된 저장소 삭제.
      if(fileBuf != NULL) { delete [] fileBuf; fileBuf = NULL; }

  //}

  //[관리 정보 초기화]
  //{
      //[주의]{------------------------------------------------------------
      //새로 열 [문서] 의 [문서정보] 를 완전히 초기화 한다.
      //_linecount 도 아래 함수에서 초기화 되므로 먼저 처리해 주어야 한다.
      //}------------------------------------------------------------------

      _ROOT_TEXTINFO_Init();
      
  //}

  //[문서 종류 확인]
  //{
      //[2009.05.28.목][수정!!!]{----------------------------
      //이전 이 확인 부분을 간단하게 함수로 만들어 대체한다.
      //}----------------------------------------------------

      _EditFile_SetKind(fileName.c_str());

  //}

  //[문서 총 행수 구하기]
  //{
      //이미 열어 놓은 문서의 총 행수를 구하여 전역변수에 기록해 놓는다.
      _linecount = STR_Get_LineCount(_editbuf);

  //}

  //[부가 처리]
  //{
      //문서양에 맞게 다시 스크롤을 설정한다.
      //[문서] 를 처음 연 것이므로 [스크롤] 을 전부 다시 설정한다.
      _Scroll_Set();

  //}

  //[문서 출력]
  //{
      //불러들인 문서를 [편집기] 에 출력하여 보여준다.
      _EditBuf_Text();
      
  //}

  //[임시 문서 만들기]
  //{
      //[2007.03.22.목][추가!!!]{--------------------------------------------------------------
      //"*.*~" 으로 현재 [문서이름] 에 "~" 문자를 덧붙여 [임시문서이름] 을 만든후
      //현재 열려 있는 파일을 다시 [임시문서] 에 저장한다.(즉, 새로 복제된 임시문서를 만든다.)
      //[임시문서] 는 원본과 같은 위치에 있어야 한다.
      //}--------------------------------------------------------------------------------------

      //[임시문서이름] 만들기.(끝에 '~' 문자를 붙여주면 된다.)
      tempfilename = fileName + "~";

      //임시문서저장.
      //[2021.01.17.일][수정]
      //<_filesize> 는 '\0' 까지 포함된 크기이므로, <FILE_Save()> 로 저장시에는 '\0' 크기를
      //제외한 크기로 저장해야 한다.---------------------------------v
      FILE_Save(tempfilename, (unsigned char *)_editbuf, _filesize - 1);
      
  //}

  //[책갈피 재설정]
  //{
      //[2012.03.01.목][추가!!!]{------------------------------------------------
      //현재 문서의 [책갈피 문서] 가 존재한다면 읽어들여 [책갈피] 에 재설정한다.
      //}------------------------------------------------------------------------

      if(_bookMark_DialogBox->_enable == true)
      {
        _bookMark_DialogBox->_FileOpen(fileName.c_str());

      }

  //}

  return;

}

/*
void __fastcall Teditor_edit_Form::_EDITFILE_Open(AnsiString  pFILEname)
{
  //[2006.12.16.토][생성!!!]{-------------------------------------------------------
  //지정된 [문서] 를 읽어서 _editbuf[] 에 넣어 준다.
  //이전에 _editbuf[] 안의 내용은 완전히 무시한다.
  //문서를 다시 표시하고 스크롤정보등도 이에 맞게 다시 수정하며 [편집기] 에
  //보여주는 것까지 완전히 처리한다.
  //
  //[2006.12.28.목][추가!!!]--------------------------------------------------------
  //[문서] 를 열어주는 시점에서 [문서] 총 행수를 구하여 전역변수에 저장한다.
  //
  //[2007.01.04.목][수정!!!]--------------------------------------------------------
  //문서를 처음 여는 경우만 사용하므로 기본 정보도 역시 전부 초기화 해 주어야 한다.
  //
  //[2007.01.10.수][수정!!!]--------------------------------------------------------
  //연 문서의 byte 단위 크기를 반드시 기록해 놓는다.
  //
  //[2007.03.23.금][수정!!!]--------------------------------------------------------
  //[문서] 를 열면서 자동으로 복제 [임시문서] 를 생성하여 저장한다.
  //이는 사용자가 직접 저장하기 전까지는 원본을 손상시키지 않기 위한 것이다.
  //문서전환시 이전에 수정한 문서를 자동으로 저장하게 되는데, 이때 이 [임시문서] 를
  //사용하여 처리하게 되고 새로 전환시 여는 문서도 바로 [임시문서] 가 된다.
  //즉, [문서] 는 오로지 사용자가 직접 저장하는 경우만 실제 수정된 내용이 저장된다.
  //
  //[2007.03.29.목][수정!!!]--------------------------------------------------------
  //[문서이름] 이 "새문서.XXX" 인 경우는 [새문서] 이므로 전용 지정 폴더위치의
  //[문서이름] 으로 변환하여 사용해야 한다.
  //
  //[2009.04.01.수][중요수정!!!]----------------------------------------------------
  //[문서] 를 열때 [확장자] 에 따라서 편집속성을 달리해 주어야 한다.
  //특별 처리 대상이 되는 문서는 아래와 같다.
  //<*.c>, <*.gasm>, <*.gcsm> 3개 종류가 된다.
  //
  //[2012.03.01.목][추가!!!]--------------------------------------------------------
  //[현재 여는 문서] 와 같은 위치에 해당 [책갈피 문서] 가 있다면 [책갈피] 에 설정.
  //}-------------------------------------------------------------------------------

  //[VAR]
  //{
      int         filesize;

      //[2007.03.23.금][추가!!1]
      //pFILEname 의 복제 [임시문서이름] 을 저장한다.
      AnsiString  tempfilename = "";

      //[2007.03.29.목][추가!!!]
      //임시 파일이 존재할 path 를 미리 만들어 놓는다.
      //무조건 *.exe 의 [temp] 폴더에 저장된다.
      AnsiString  newfilepath = ExtractFilePath(Application->ExeName) + "temp\\";

      //"새문서" 인지 확인만 하므로 '\0' 까지 7 byte 면 충분하다.
      char        word[7];

      AnsiString  filename = "";

      //[2009.04.01.수][추가!!!]
      //현재 문서의 [확장자] 만 추출한다.
      char        fileExtStr[OPT_wordStrSize];

  //}

  //["새문서" 인가?]
  //{
      //[2007.03.29.목][추가!!!]
      //[새문서] 인 경우는 전용 공간에 [문서] 가 존재하므로 이곳에서 해당 이름의
      //문서를 찾아서 열어 주어야 한다.
      //처음 6 byte 만 읽어서 저장하면 쉽게 확인할수 있다.
      memmove(word, pFILEname.c_str(), 6);

      //문자열로 만든다.
      word[6] = '\0';

      //"새문서" 라면 실제 [문서이름] 으로 완성해 준다.
      if(STR_Match(word, "새문서") == true)
      {
        //[새문서] 의 전체 [문서이름] 을 만들어 준다.
        filename = newfilepath + pFILEname;

      }
      else
      {
        //전달된 이름을 그대로 사용한다.
        filename = pFILEname;

      }

  //}

  //[문서 열기]
  //{
      FILE_Open_inBUF(filename, _editbuf, &filesize);

      //현재 [문서크기] 를 기록해 놓는다.
      _filesize = filesize;

  //}

  //[관리 정보 초기화][주의!!!]
  //{
      //-------------------------------------------------------------------
      //새로 열 [문서] 의 [문서정보] 를 완전히 초기화 한다.
      //_linecount 도 아래 함수에서 초기화 되므로 먼저 처리해 주어야 한다.
      _ROOT_TEXTINFO_Init();
      //-------------------------------------------------------------------
  //}

  //[문서 종류 확인]
  //{
      //[2009.05.28.목][수정!!!]{----------------------------
      //이전 이 확인 부분을 간단하게 함수로 만들어 대체한다.
      //}----------------------------------------------------

      _EditFile_SetKind(filename.c_str());

  //}

  //[문서 총 행수 구하기]
  //{
      //이미 열어 놓은 문서의 총 행수를 구하여 전역변수에 기록해 놓는다.
      _linecount = STR_Get_LineCount(_editbuf);

  //}

  //[부가 처리]
  //{
      //문서양에 맞게 다시 스크롤을 설정한다.
      //[문서] 를 처음 연 것이므로 [스크롤] 을 전부 다시 설정한다.
      _Scroll_Set();

  //}

  //[문서 출력]
  //{
      //불러들인 문서를 [편집기] 에 출력하여 보여준다.
      _EditBuf_Text();
      
  //}

  //[임시 문서 만들기]
  //{
      //[2007.03.22.목][추가!!!]{--------------------------------------------------------------
      //"*.*~" 으로 현재 [문서이름] 에 "~" 문자를 덧붙여 [임시문서이름] 을 만든후
      //현재 열려 있는 파일을 다시 [임시문서] 에 저장한다.(즉, 새로 복제된 임시문서를 만든다.)
      //[임시문서] 는 원본과 같은 위치에 있어야 한다.
      //}--------------------------------------------------------------------------------------

      //[임시문서이름] 만들기.(끝에 '~' 문자를 붙여주면 된다.)
      tempfilename = filename + "~";

      //임시문서저장.
      FILE_Save(tempfilename, (unsigned char *)_editbuf, _filesize);
      
  //}

  //[책갈피 재설정]
  //{
      //[2012.03.01.목][추가!!!]{------------------------------------------------
      //현재 문서의 [책갈피 문서] 가 존재한다면 읽어들여 [책갈피] 에 재설정한다.
      //}------------------------------------------------------------------------

      if(_bookMark_DialogBox->_enable == true)
      {
        _bookMark_DialogBox->_FileOpen(filename.c_str());

      }

  //}

  return;

}
*/

void __fastcall Teditor_edit_Form::_EDITFILE_ReOpen(AnsiString  pFILEname)
{
  //[2007.01.04.토][생성!!!]{-----------------------------------------------------------
  //_EDITFILE_Open() 함수와 내용은 같으나, 이 함수는 이전에 열었던 문서를
  //다시 열어주는 경우 사용된다.
  //차이점은 이미 [스크롤] 정보가 있으므로 초기화 하지 않는다는 것이다.
  //따라서 _Scroll_Resize() 함수를 사용한다.
  //
  //[2007.03.23.금][수정!!!]------------------------------------------------------------
  //[문서전환] 시에 이 함수가 사용되는데, 이때는 반드시 [임시파일] 을 열어 주어야 한다.
  //이는 원본은 사용자가 직접 저장하는 경우만 수정내용이 반영되어야 하기 때문이다.
  //
  //[2007.03.29.목][수정!!!]------------------------------------------------------------
  //[문서이름] 이 "새문서.XXX" 인 경우는 [새문서] 이므로 전용 지정 폴더위치의
  //[문서이름] 으로 변환하여 사용해야 한다.
  //
  //[주의!!!]---------------------------------------------------------------------------
  //_EDITFILE_Open() 함수와 달리 _filesize, _linecount 를 기록할 필요는 없다.
  //_TEXTINFO_Restore() 함수로 자동으로 이전 정보가 복구 되므로.
  //
  //[2012.03.01.목][추가!!!]------------------------------------------------------------
  //[현재 여는 문서] 와 같은 위치에 해당 [책갈피 문서] 가 있다면 [책갈피] 에 설정.
  //}-----------------------------------------------------------------------------------

  //[VAR]
  //{
      int         filesize;

      //[2007.03.23.금][추가!!1]
      //pFILEname 의 복제 [임시문서이름] 을 저장한다.
      AnsiString  tempfilename;

      //[2007.03.29.목][추가!!!]
      //임시 파일이 존재할 path 를 미리 만들어 놓는다.
      //무조건 *.exe 의 [temp] 폴더에 저장된다.
      AnsiString  newfilepath = ExtractFilePath(Application->ExeName) + "temp\\";

      //"새문서" 인지 확인만 하므로 '\0' 까지 7 byte 면 충분하다.
      char        word[7];

      AnsiString  filename = "";
  //}

  //["새문서" 인가?]
  //{
      //[2007.03.29.목][추가!!!]{------------------------------------------------
      //[새문서] 인 경우는 전용 공간에 [문서] 가 존재하므로 이곳에서 해당 이름의
      //문서를 찾아서 열어 주어야 한다.
      //처음 6 byte 만 읽어서 저장하면 쉽게 확인할수 있다.
      //}------------------------------------------------------------------------

      memmove(word, pFILEname.c_str(), 6);

      //문자열로 만든다.
      word[6] = '\0';

      //"새문서" 라면 실제 [문서이름] 으로 완성해 준다.
      if(STR_Match(word, "새문서") == true)
      {
        //[새문서] 의 전체 [문서이름] 을 만들어 준다.
        filename = newfilepath + pFILEname;

      }
      else
      {
        //전달된 이름을 그대로 사용한다.
        filename = pFILEname;

      }

  //}

  //[문서 열기]
  //{
      //[2007.03.22.목][수정!!!]{----------------------------------------
      //"*.*~" 로 [임시문서이름] 으로 변경후 이 문서를 열어 주어야 한다.
      //현재 [편집중] 인 문서는 "*.*~" 이고, "*.*" 는 [원본] 으로 반드시
      //사용자가 직접 [저장] 하는 경우만 "*.*~" 의 내용이 저장된다.
      //}----------------------------------------------------------------

      //[임시문서이름] 만들기.(끝에 '~' 문자를 붙여주면 된다.)
      tempfilename = filename + "~";

      //[임시문서] 열기.
      FILE_Open_inBUF(tempfilename, _editbuf, &filesize);

  //}

  //[문서 출력][일단유보!!!]
  //{
      //[!]----------------------------------------------------------------
      //불러들인 문서를 [편집기] 에 출력하여 보여준다.
      //_EditBuf_Text();
      //처음 여는 것이 아니고, 어차피 _TEXTINFO_Restore() 등 다음 함수에서
      //_Position() 함수가 호출되면 자동으로 [스크롤] 이 되어 다시 문서가
      //표시되므로 굳이 여기서 표시할 필요는 없다.
      //-------------------------------------------------------------------
  //}

  //[현재 문서 정보 복구]
  //{
      //새로 연 문서정보를 다시 설정해서 복구한다.
      _TEXTINFO_Restore(_textinfo_index);

      //[정확한 파일 크기 처리]
      //{
          //[2021.01.15.금][추가]{***************************************
          //정확한 내용은 이 문서의 같은 날짜로 찾은 첫번째 설명을 참고.
          //}************************************************************

          //편집기에 들어있는 실제 문자열의 길이로 설정(보정)한다.
          //'\0' 크기 포함---------------------------------------------v
          _textinfo[_textinfo_index].filesize = STR_Length(_editbuf) + 1;

          _filesize = _textinfo[_textinfo_index].filesize;

      //}

  //}

  //[묶음주석 정보 얻기]
  //{
      //[2009.06.06.토][추가!!!]{--------------------------------------------
      //문서를 다시 여는 경우는 _EditFile_SetKind() 함수를 호출하지 않으므로
      //이 안에서 자동으로 처리되는 [묶음주석] 정보를 얻지 못하게 된다.
      //따라서 이 정보만 직접 구한다.
      //}--------------------------------------------------------------------

      //[2012.06.12.화][수정!!!]{---------------
      //문서를 열때 는 문서 처음부터 정보 수집.
      //}---------------------------------------
      //-----------------v
      _CommentBlock_Info(false);

  //}

  //[부가 처리]
  //{
      //문서량에 맞게 다시 스크롤을 설정한다.
      //단, 이미 연 문서이므로 크기만 다시 조정하는 것이다.
      _Scroll_Resize();

      //[주의!!!][2007.01.06.토]
      //{
          //[!]----------------------------------------------------------------------------------------------
          //_Scroll_Resize() 함수는 반드시 _TEXTINFO_Restore() 다음에 있어야 한다.
          //이는 _TEXTINFO_Restore() 함수에서 _Position() 으로 다시 위치가 설정되므로
          //_Scroll_Resize() 함수를 먼저 사용하게 되면 결과적으로 _Position(이전위치) -> _Position(지금위치)
          //로 두번 사용하는 꼴이 되어 [thumb] 의 움직임이 수정되는 것이 보여 보기 좋지 않다.(깜박임 문제)
          //따라서, 반드시 가장 나중에 호출하여 준다.
          //-------------------------------------------------------------------------------------------------
      //}

  //}

  //[책갈피 재설정]
  //{
      //[2012.03.01.목][추가!!!]{------------------------------------------------
      //현재 문서의 [책갈피 문서] 가 존재한다면 읽어들여 [책갈피] 에 재설정한다.
      //}------------------------------------------------------------------------

      if(_bookMark_DialogBox->_enable == true)
      {
        _bookMark_DialogBox->_FileOpen(filename.c_str());

      }

  //}

}

/*
void __fastcall Teditor_edit_Form::_EDITFILE_Open(AnsiString  pFILEname)
{
  //[2006.12.16.토][생성!!!]{-------------------------------------------------------
  //지정된 [문서] 를 읽어서 _editbuf[] 에 넣어 준다.
  //이전에 _editbuf[] 안의 내용은 완전히 무시한다.
  //문서를 다시 표시하고 스크롤정보등도 이에 맞게 다시 수정하며 [편집기] 에
  //보여주는 것까지 완전히 처리한다.
  //
  //[2006.12.28.목][추가!!!]--------------------------------------------------------
  //[문서] 를 열어주는 시점에서 [문서] 총 행수를 구하여 전역변수에 저장한다.
  //
  //[2007.01.04.목][수정!!!]--------------------------------------------------------
  //문서를 처음 여는 경우만 사용하므로 기본 정보도 역시 전부 초기화 해 주어야 한다.
  //
  //[2007.01.10.수][수정!!!]--------------------------------------------------------
  //연 문서의 byte 단위 크기를 반드시 기록해 놓는다.
  //
  //[2007.03.23.금][수정!!!]--------------------------------------------------------
  //[문서] 를 열면서 자동으로 복제 [임시문서] 를 생성하여 저장한다.
  //이는 사용자가 직접 저장하기 전까지는 원본을 손상시키지 않기 위한 것이다.
  //문서전환시 이전에 수정한 문서를 자동으로 저장하게 되는데, 이때 이 [임시문서] 를
  //사용하여 처리하게 되고 새로 전환시 여는 문서도 바로 [임시문서] 가 된다.
  //즉, [문서] 는 오로지 사용자가 직접 저장하는 경우만 실제 수정된 내용이 저장된다.
  //
  //[2007.03.29.목][수정!!!]--------------------------------------------------------
  //[문서이름] 이 "새문서.XXX" 인 경우는 [새문서] 이므로 전용 지정 폴더위치의
  //[문서이름] 으로 변환하여 사용해야 한다.
  //
  //[2009.04.01.수][중요수정!!!]----------------------------------------------------
  //[문서] 를 열때 [확장자] 에 따라서 편집속성을 달리해 주어야 한다.
  //특별 처리 대상이 되는 문서는 아래와 같다.
  //<*.c>, <*.gasm>, <*.gcsm> 3개 종류가 된다.
  //
  //[2012.03.01.목][추가!!!]--------------------------------------------------------
  //[현재 여는 문서] 와 같은 위치에 해당 [책갈피 문서] 가 있다면 [책갈피] 에 설정.
  //}-------------------------------------------------------------------------------

  //[VAR]
  //{
      int         filesize;

      //[2007.03.23.금][추가!!1]
      //pFILEname 의 복제 [임시문서이름] 을 저장한다.
      AnsiString  tempfilename = "";

      //[2007.03.29.목][추가!!!]
      //임시 파일이 존재할 path 를 미리 만들어 놓는다.
      //무조건 *.exe 의 [temp] 폴더에 저장된다.
      AnsiString  newfilepath = ExtractFilePath(Application->ExeName) + "temp\\";

      //"새문서" 인지 확인만 하므로 '\0' 까지 7 byte 면 충분하다.
      char        word[7];

      AnsiString  filename = "";

      //[2009.04.01.수][추가!!!]
      //현재 문서의 [확장자] 만 추출한다.
      char        fileExtStr[OPT_wordStrSize];

  //}

  //["새문서" 인가?]
  //{
      //[2007.03.29.목][추가!!!]
      //[새문서] 인 경우는 전용 공간에 [문서] 가 존재하므로 이곳에서 해당 이름의
      //문서를 찾아서 열어 주어야 한다.
      //처음 6 byte 만 읽어서 저장하면 쉽게 확인할수 있다.
      memmove(word, pFILEname.c_str(), 6);

      //문자열로 만든다.
      word[6] = '\0';

      //"새문서" 라면 실제 [문서이름] 으로 완성해 준다.
      if(STR_Match(word, "새문서") == true)
      {
        //[새문서] 의 전체 [문서이름] 을 만들어 준다.
        filename = newfilepath + pFILEname;

      }
      else
      {
        //전달된 이름을 그대로 사용한다.
        filename = pFILEname;

      }

  //}

  //[문서 열기]
  //{
      //CRLF 완성 처리.

      






      FILE_Open_inBUF(filename, _editbuf, &filesize);





      

      //현재 [문서크기] 를 기록해 놓는다.
      _filesize = filesize;

  //}

  //[관리 정보 초기화][주의!!!]
  //{
      //-------------------------------------------------------------------
      //새로 열 [문서] 의 [문서정보] 를 완전히 초기화 한다.
      //_linecount 도 아래 함수에서 초기화 되므로 먼저 처리해 주어야 한다.
      _ROOT_TEXTINFO_Init();
      //-------------------------------------------------------------------
  //}

  //[문서 종류 확인]
  //{
      //[2009.05.28.목][수정!!!]{----------------------------
      //이전 이 확인 부분을 간단하게 함수로 만들어 대체한다.
      //}----------------------------------------------------

      _EditFile_SetKind(filename.c_str());

  //}

  //[문서 총 행수 구하기]
  //{
      //이미 열어 놓은 문서의 총 행수를 구하여 전역변수에 기록해 놓는다.
      _linecount = STR_Get_LineCount(_editbuf);

  //}

  //[부가 처리]
  //{
      //문서양에 맞게 다시 스크롤을 설정한다.
      //[문서] 를 처음 연 것이므로 [스크롤] 을 전부 다시 설정한다.
      _Scroll_Set();

  //}

  //[문서 출력]
  //{
      //불러들인 문서를 [편집기] 에 출력하여 보여준다.
      _EditBuf_Text();
      
  //}

  //[임시 문서 만들기]
  //{
      //[2007.03.22.목][추가!!!]{--------------------------------------------------------------
      //"*.*~" 으로 현재 [문서이름] 에 "~" 문자를 덧붙여 [임시문서이름] 을 만든후
      //현재 열려 있는 파일을 다시 [임시문서] 에 저장한다.(즉, 새로 복제된 임시문서를 만든다.)
      //[임시문서] 는 원본과 같은 위치에 있어야 한다.
      //}--------------------------------------------------------------------------------------

      //[임시문서이름] 만들기.(끝에 '~' 문자를 붙여주면 된다.)
      tempfilename = filename + "~";

      //임시문서저장.
      FILE_Save(tempfilename, (unsigned char *)_editbuf, _filesize);
      
  //}

  //[책갈피 재설정]
  //{
      //[2012.03.01.목][추가!!!]{------------------------------------------------
      //현재 문서의 [책갈피 문서] 가 존재한다면 읽어들여 [책갈피] 에 재설정한다.
      //}------------------------------------------------------------------------

      if(_bookMark_DialogBox->_enable == true)
      {
        _bookMark_DialogBox->_FileOpen(filename.c_str());

      }

  //}

  return;

}
*/
void __fastcall Teditor_edit_Form::_EDITFILE_TempDelete(char  *pFileFullName)
{
  //[2009.05.05.화][생성!!!]{-------------------------------------------------
  //<*.*> 문서 이름을 전달 받아서 이 문서의 임시문서인 <*.*~> 를 삭제해 준다.
  //이 두 문서는 항상 같은 위치에 존재한다.
  //단, [새문서] 인 경우는 전용 경로가 있으므로 이를 구분하여 처리해야 한다.
  //
  //(1) <*.*> 문서이름으로 삭제할 <*.*~> 문성이름을 만든다.
  //(2) <*.*~> 문서를 삭제한다.
  //}-------------------------------------------------------------------------

  //[VAR]
  //{
      //<*.urd> 문서의 경로를 저장한다.
      char   fileName[OPT_filepath_length];
      char   tempWord[OPT_wordStrSize];

  //}

  //[문서이름 구분 처리]
  //{
      //[!]{-------------------------------------------------------------
      //[새문서] 인 경우는 별도 경로로 [문서이름] 을 합성해 주어야 한다.
      //처음 6 byte 만 읽어서 저장하면 쉽게 확인할수 있다.
      memmove(tempWord, pFileFullName, 6);
      //문자열로 만든다.
      tempWord[6] = '\0';
      //}----------------------------------------------------------------

      if(STR_Match(tempWord, "새문서") == true)
      {
        //"새문서" 라면 실제 [문서이름] 으로 완성해 준다.

        //[임시문서] 의 고정 경로를 할당해 준다.
		STR_Assign(fileName, ((AnsiString)ExtractFilePath(Application->ExeName)).c_str());
        STR_Add(fileName, "temp\\");

        //문서이름 합성.
        STR_Add(fileName, pFileFullName);

      }
      else
      {
        //일반 문서인 경우는 그대로 사용한다.
        STR_Assign(fileName, pFileFullName);

      }

  //}

  //[임시문서 기호 만들기]
  //{
      //[!]{--------------------------------------------------
      //[임시문서] 이름을 만들기 위하여 뒤에 "~" 가 붙여준다.
      //}-----------------------------------------------------

      STR_Add_AB(fileName, fileName, "~");

  //}

  //[존재확인]
  //{
      //[삭제] 하려는 문서가 존재하지 않는다면 더이상 처리하지 않는다.
      if(FileExists(fileName) != true) return;

  //}

  //[문서 삭제]
  //{
      //지정된 문서를 삭게한다.
      DeleteFile(fileName);

  //}

  return;

}

void __fastcall Teditor_edit_Form::_EDITFILE_SaveNowFile_inTEMPfile(void)
{
  //[2007.03.23.금][생성!!!]{-------------------------------------------------
  //현재 편집중인 문서를 해당 [임시문서이름] 으로 저장한다.
  //이 함수는 [문서전환] 시에 새 문서를 열기 전에 호출된다.

  //[2007.03.29.목][수정!!!]--------------------------------------------------
  //[문서이름] 이 "새문서.XXX" 인 경우는 [새문서] 이므로 전용 지정 폴더위치의
  //[문서이름] 으로 변환하여 사용해야 한다.
  //
  //[2012.03.01.목][추가!!!]--------------------------------------------------
  //이 문서 저장 위치에 현재 [책갈피] 의 내용을 [책갈피 문서] 로 저장.
  //}-------------------------------------------------------------------------

  //[주의!!!]
  //{
      //_filesize 는 문자열전체크기로써 '\0' 크기 가지 포함되 있는데,
      //'\0' 까지 저장하는 경우는 다른 *.txt 파일등과 호환이 되지 않으므로
      //'\0' 을 제외하고 저장해 주어야 한다.
  //}

  //[VAR]
  //{
      //현재 편집중인 문서의 복제 [임시문서이름] 을 저장한다.
      AnsiString  tempfilename;

      //[2007.03.29.목][추가!!!]
      //임시 파일이 존재할 path 를 미리 만들어 놓는다.
      //무조건 *.exe 의 [temp] 폴더에 저장된다.
      AnsiString  newfilepath = ExtractFilePath(Application->ExeName) + "temp\\";

      //"새문서" 인지 확인만 하므로 '\0' 까지 7 byte 면 충분하다.
      char        word[7];

      AnsiString  filename = "";
  //}

  //[안전장치]
  //{
      //[2007.03.31.토][추가!!!]
      //현재 열려 있는 문서가 없는 경우는 처리하지 않아야 한다.
      if(_textinfo_count == 0) return;
  //}

  //["새문서" 인가?]
  //{
      //[2007.03.29.목][추가!!!]
      //[새문서] 인 경우는 전용 공간에 [문서] 가 존재하므로 이곳에서 해당 이름의
      //문서를 찾아서 열어 주어야 한다.
      //처음 6 byte 만 읽어서 저장하면 쉽게 확인할수 있다.
      memmove(word, _textinfo[_textinfo_index].filename.c_str(), 6);

      //문자열로 만든다.
      word[6] = '\0';

      //"새문서" 라면 실제 [문서이름] 으로 완성해 준다.
      if(STR_Match(word, "새문서") == true)
      {
        //[새문서] 의 전체 [문서이름] 을 만들어 준다.
        filename = newfilepath + _textinfo[_textinfo_index].filename;

      }
      else
      {
        //전달된 이름을 그대로 사용한다.
        filename = _textinfo[_textinfo_index].filename;

      }
      
  //}

  //[임시 문서 만들기]
  //{
      //[2007.03.22.목][추가!!!]{--------------------------------------------------------------
      //"*.*~" 으로 현재 [문서이름] 에 "~" 문자를 덧붙여 [임시문서이름] 을 만든후
      //현재 열려 있는 파일을 다시 [임시문서] 에 저장한다.(즉, 새로 복제된 임시문서를 만든다.)
      //[임시문서] 는 원본과 같은 위치에 있어야 한다.
      //}--------------------------------------------------------------------------------------

      //[임시문서이름] 만들기.(끝에 '~' 문자를 붙여주면 된다.)
      tempfilename = filename + "~";

      //[정확한 파일 크기 처리]
      //{
          //[2021.01.15.금][추가]{***************************************
          //정확한 내용은 이 문서의 같은 날짜로 찾은 첫번째 설명을 참고.
          //}************************************************************

          //편집기에 들어있는 실제 문자열의 길이로 설정(보정)한다.
          //'\0' 크기 포함-------------------v
          _filesize = STR_Length(_editbuf) + 1;

      //}

      //임시문서저장.
      FILE_Save(tempfilename, (unsigned char *)_editbuf,
                //가장 마지막의 '\0' 는 제외하고 저장한다.
                _filesize - 1);
  //}

  //[책갈피 저장]
  //{
      //[2012.03.01.목][추가!!!]{--------------------------------------------------
      //현재 문서의 [책갈피] 내용을 현재 문서와 같은 위치에 [책갈피 문서] 로 저장.
      //}--------------------------------------------------------------------------

      if(_bookMark_DialogBox->_enable == true)
      {
        _bookMark_DialogBox->_FileSave(filename.c_str());

      }

  //}

  return;

}

void __fastcall Teditor_edit_Form::_EDITFILE_SaveNowEditFile(void)
{
  //[2007.03.23.금][생성!!!]{-------------------------------------------------------
  //현재 편집중인 문서를 해당 [문서이름] 그대로 저장한다.
  //이 함수는 사용자가 직접 수정한 문서를 저장하는 경우 호출된다.
  //
  //[2007.03.29.목][수정!!!]---------------------------------------------------------
  //[문서이름] 이 "새문서.XXX" 인 경우는 아직 저장되지 않은 문서이므로 무조건
  //[저장대화상자] 를 출력하여 사용자가 직접 경로를 지정할수 있게 만들어야 한다.
  //또한, 사용자가 지정한 [문서이름] 으로 [새문서] 의 이름을 바꾸어 주어야 한다.
  //
  //[2007.03.29.목][추가수정!!!]-----------------------------------------------------
  //만일 [새문서] 를 저장하는데 이미 같은 이름의 문서가 있는 경우는 덮어쓸지
  //묻는 대화상자를 출력하고 [확인] 이 반환되면 이전 문서를 덮어서 저장하고,
  //해당 정보도 완전히 대체해 주어야 한다.
  //목록은 하나 줄어 들었으므로 현재 [새문서] 는 [문서관리정보] 까지 삭제해야 한다.
  //
  //[2007.04.05.목][수정!!!]---------------------------------------------------------
  //문서가 저장된 경우는 [수정] 에서 해제해 주어야 한다.                 
  //
  //[2009.05.28.목][수정!!!]---------------------------------------------------------
  //[새문서] 를 저장시에는 반드시 해당 문서의 종류를 구분하여 해당 설정을 해야 한다.
  //
  //[2012.03.01.목][추가!!!]---------------------------------------------------------
  //이 문서 저장 위치에 현재 [책갈피] 의 내용을 [책갈피 문서] 로 저장.
  //}--------------------------------------------------------------------------------

  //[VAR]
  //{
      //[2007.03.29.목][추가!!!]{---------------------------------
      //"새문서" 인지 확인만 하므로 '\0' 까지 7 byte 면 충분하다.
      //}---------------------------------------------------------

      char  word[7];

  //}

  //[안전장치]
  //{
      //[2007.03.31.토][추가!!!]{-------------------------------
      //현재 열려 있는 문서가 없는 경우는 처리하지 않아야 한다.
      //}-------------------------------------------------------

      if(_textinfo_count == 0) return;

  //}

  //["새문서" 인가?]
  //{
      //[2007.03.29.목][추가!!!]{------------------------------------------------------------------------
      //[새문서] 인 경우는 전용 공간에 [문서] 가 존재하므로 이곳에서 해당 이름의 문서를 찾아주어야 한다.
      //처음 6 byte 만 읽어서 저장하면 쉽게 확인할수 있다.
      memmove(word, _textinfo[_textinfo_index].filename.c_str(), 6);
      //}------------------------------------------------------------------------------------------------

      //문자열로 만든다.
      word[6] = '\0';

      //"새문서" 라면 실제 [문서이름] 으로 완성해 준다.
      if(STR_Match(word, "새문서") == true)
      {
        //[새문서] 의 경우는 아직 저장된 것이 아니므로 사용자가 경로를 지정할수
        //있도록 [저장대화상자] 를 열어준다.

        main_Form->file_SaveDialog->Filter = "*.c|*.c|*.h|*.h|*.txt|*.txt|*.gtxt|*.gtxt|*.gasm|*.gasm|*.gcsm|*.gcsm|*.gobj|*.gobj|*.glib|*.glib|*.gob1|*.gob1|*.gtmp|*.gtmp";

        //저장하지 않는 경우는 그냥 종료한다.
        if(main_Form->file_SaveDialog->Execute() != true) return;

        //[이름이 같은 경우 처리]
        //{
            //[2007.03.30.금][수정!!!]{--------------------------------
            //사용자가 지정한 이름의 문서가 이미 있는 경우를 처리한다.
            //}--------------------------------------------------------

            //[중복확인]
            //{
                if(FileExists(main_Form->file_SaveDialog->FileName) == true)
                {
                  //중복된 경우는 중복된 이름으로 이미 있는 문서를 지금의 문서로 덮어쓸지
                  //묻는 대화상자를 표시한다.
                  if(ide_msgbox_Form->_MsgBox_Ok_Cancle(d_MSGBOX_info, //d_MSGBOX_default,
                                                        "이미 존재하는 [문서이름] 입니다.\r\n"
                                                        "이전 문서를 지금 문서로 덮어쓸까요?") == true)
                  {
                    //[확인] 이 눌린 경우.

                    //[목록에 이미 있는 경우인가?]
                    //{
                        if(_TEXTINFO_GetIndex_withFILEname(main_Form->file_SaveDialog->FileName) >= 0)
                        {
                          //[문서목록] 에 이미 있는 경우는 혼란을 방지하기 위하여 저장하지 않으며,
                          //사용자에게 경고 문구로 알려준다.
                          ide_msgbox_Form->_MsgBox(d_MSGBOX_error,
                                                   "이미 열려있는 [문서이름] 으로는 저장할 수 없습니다.\r\n"
                                                   "다른 이름으로 다시 저장하십시요.");

                          //바로 종료한다.
                          return;

                        }
                        else
                        {
                          //이 경우는 [문서목록] 에는 없으므로 다음 처리부에서 그냥 덮어서 저장하도록 놔둔다.

                        }

                    //}

                  }
                  else
                  {
                    //[취소] 가 눌린 경우.
                    //아무것도 처리하지 않고 종료한다.
                    return;

                  }

                }

            //}

        //}

        //[제목줄 표시]
        //{
            //사용자가 지정한 새로운 이름을 기록한다.
            _textinfo[_textinfo_index].filename = main_Form->file_SaveDialog->FileName;

            //현재 새로운 [문서이름] 을 제목줄에 표시한다.
            //[제목줄] 을 다시 그리는 것으로 자동 반영된다.
            editor_top_Form->_Shape();

        //}

        //[문서 종류 설정]
        //{
            //[2009.05.28.목][추가!!!]{------------------------------------------------------------------
            //현재문서를 <*.c/h/gtxt> 등으로 새로 저장하는 경우는 바로 해당 [색동문자] 를 적용해야 한다.
            //또한 부가적인 추가 설정을 수행한다.
            //이 경우는 바로 반영 될수 있도록 현재 [편집기] 를 다시 그려 주어야 한다.
            //}------------------------------------------------------------------------------------------

            if(_EditFile_SetKind(_textinfo[_textinfo_index].filename.c_str()) == true)
            {
              //전체를 다시 그려준다.
              _EditBuf_Text();

            }

        //}

      }

  //}

  //[문서 저장]
  //{
      //[정확한 파일 크기 처리]
      //{
          //[2021.01.15.금][추가]{***************************************
          //정확한 내용은 이 문서의 같은 날짜로 찾은 첫번째 설명을 참고.
          //}************************************************************

          //편집기에 들어있는 실제 문자열의 길이로 설정(보정)한다.
          //'\0' 크기 포함---------------------------------------------v
          _textinfo[_textinfo_index].filesize = STR_Length(_editbuf) + 1;

          _filesize = _textinfo[_textinfo_index].filesize;

      //}

      FILE_Save(_textinfo[_textinfo_index].filename, (unsigned char *)_editbuf,
                //가장 마지막의 '\0' 는 제외하고 저장한다.
                _filesize - 1);

  //}

  //[문서수정없음]
  //{
      //[2007.04.05.목][추가!!!]{-------------------------
      //문서를 저장하였으므로 수정된것이 없음을 기록한다.
      //}-------------------------------------------------

      _EDIT_Changed(true, false);

  //}

  //[책갈피 저장]
  //{
      //[2012.03.01.목][추가!!!]{--------------------------------------------------
      //현재 문서의 [책갈피] 내용을 현재 문서와 같은 위치에 [책갈피 문서] 로 저장.
      //}--------------------------------------------------------------------------

      if(_bookMark_DialogBox->_enable == true)
      {
        _bookMark_DialogBox->_FileSave(_textinfo[_textinfo_index].filename.c_str());

      }

  //}

  return;

}

void __fastcall Teditor_edit_Form::_EDITFILE_SaveAllFile(void)
{
  //[2007.03.23.금][생성!!!]{--------------------------------------------------
  //현재 열려 있는 모든 문서를 전부 저장한다.
  //_textinfo[] 정보 를 사용하여 간단하게 처리 할수 있다.
  //
  //[2007.03.29.목][수정!!!]---------------------------------------------------
  //이 경우는 단순 저장과 달리 [문서이름] 이 "새문서.XXX" 인 경우는 대화상자를
  //출력하지 않고 그냥 [새문서] 경로에 저장한다.
  //[새문서] 가 많이 있는 경우 일일히 대화상자를 출력한다면 짜증난다.
  //
  //이 함수는 사용자가 직접 저장하는 것이므로 이미 지정된 이름의 경로가 있는
  //경우는 무조건 원래문서로 저장해야 한다.
  //
  //[2007.04.07.토][수정!!!]---------------------------------------------------
  //저장소를 생성할때 현재 편집중인 문서는 _filesize 를 찹고해야 한다.
  //아직, _textinfo[].filesize 에는 정확한 값이 저장되 있지 않기 때문이다.
  //
  //[2012.03.01.목][추가!!!]---------------------------------------------------
  //[책갈피] 내용을 [원본 문서] 와 같은 위치에 [책갈피 문서] 로 저장.
  //단, 이는 [현재 편집중인 문서] 만 대상으로 처리한다.
  //[책갈피 대화상자] 는 [현재 편집중인 문서] 만 대상으로 하기 때문이다. 
  //}--------------------------------------------------------------------------

  //[주의!!!]{---------------------------------------------------------
  //_filesize 는 문자열전체크기로써 '\0' 크기 가지 포함되 있는데,
  //'\0' 까지 저장하는 경우는 다른 *.txt 파일등과 호환이 되지 않으므로
  //'\0' 을 제외하고 저장해 주어야 한다.
  //}------------------------------------------------------------------

  //[VAR]
  //{
      int             i;

      int             filesize_max = 0;

      unsigned char  *filebuf = NULL;
      int             filesize;

      AnsiString      tempfilename;

      //[2007.03.29.목][추가!!!]
      //임시 파일이 존재할 path 를 미리 만들어 놓는다.
      //무조건 *.exe 의 [temp] 폴더에 저장된다.
      AnsiString      newfilepath = ExtractFilePath(Application->ExeName) + "temp\\";

      //"새문서" 인지 확인만 하므로 '\0' 까지 7 byte 면 충분하다.
      char            word[7];

      AnsiString      filename = "";

  //}

  //[안전장치]
  //{
      //[2007.03.31.토][추가!!!]
      //현재 열려 있는 문서가 없는 경우는 처리하지 않아야 한다.
      if(_textinfo_count == 0) return;
  //}

  //[가장큰 문서 크기 얻기]
  //{
      //[2007.04.07.토][수정!!!]
      //{
          //정학한 계산을 위하여 정보 구조체에 일단 현재편집중인 문서의 크기 정보를 기록한다.
          _textinfo[_textinfo_index].filesize = _filesize;
      //}

      //[!]{------------------------------------------------------------------------------
      //문서를 열때 사용할 [저장소] 를 생성하기 위하여 가장 큰 문서의 크기를 얻는다.
      //
      //[2012.03.01.목][설명추가!!!]------------------------------------------------------
      //이는 계속 <new> 로 저장 공간이 [생성/삭제] 되어 부하가 발생하는 것을 막기 위한것.
      //정말 좋은 방법이다.
      //}---------------------------------------------------------------------------------

      for(i = 0; i < _textinfo_count; i++)
      {
        if(filesize_max < _textinfo[i].filesize)
        {
          //이전 보다 지금것이 더 큰 경우는 [최대값] 으로 저장한다.
          filesize_max = _textinfo[i].filesize;

        }

      }
      //여기까지 가장 큰 크기를 얻었다.
  //}

  //[저장소 생성]
  //{
      //문서를 저장할 [저장소] 를 만든다.
      //filebuf = new unsigned char [filesize_max];
      //[동적생성단위적용][2021.01.24.일][수정]
      filebuf = new unsigned char [UnitX(1024, filesize_max)];

  //}

  //[문서 전부 저장]
  //{
      //[새문서] 인 경우는 사용자에게

      for(i = 0; i < _textinfo_count; i++)
      {
        //["새문서" 인가?]
        //{
            //[2007.03.29.목][추가!!!]
            //[새문서] 인 경우는 전용 공간에 [문서] 가 존재하므로 이곳에서 해당 이름의
            //문서를 찾아서 열어 주어야 한다.
            //처음 6 byte 만 읽어서 저장하면 쉽게 확인할수 있다.
            memmove(word, _textinfo[i].filename.c_str(), 6);

            //문자열로 만든다.
            word[6] = '\0';

            //"새문서" 라면 실제 [문서이름] 으로 완성해 준다.
            if(STR_Match(word, "새문서") == true)
            {
              //[새문서] 의 전체 [문서이름] 을 만들어 준다.
              filename = newfilepath + _textinfo[i].filename;

            }
            else
            {
              //전달된 이름을 그대로 사용한다.
              filename = _textinfo[i].filename;

            }

        //}

        //[현재문서]
        //{
            if(i == _textinfo_index)
            {
              //[기본처리]
              //{
                  //현재 편집중인 문서는 아직 해당 [임시문서] 에 수정된 내용이 반영되지
                  //않은 상태이므로 여기서 [임시문서] 로 일단 저장해 준다.
                  //다음에서 이 [임시문서] 를 다시 읽어서 저장하게 된다.
                  _EDITFILE_SaveNowFile_inTEMPfile();

                  //[정확한 파일 크기 처리]
                  //{
                      //[2021.01.15.금][추가]{***************************************
                      //정확한 내용은 이 문서의 같은 날짜로 찾은 첫번째 설명을 참고.
                      //}************************************************************

                      //정확한 <_filesize> 은 위의 <_EDITFILE_SaveNowFile_inTEMPfile()> 내부에서
                      //이미 계산되어 적용되었다.

                  //}

                  //[주의!!!]
                  //현재 파일인 경우는 아직 정보가 저장돼있지 않으므로 현재 정보를 기록해 준다.
                  //_textinfo[] 는 문서 전환시 [문서정보] 를 보관하는데 사용되기 때문이다.
                  _textinfo[i].filesize = _filesize;

              //}

              //[책갈피 문서 저장]
              //{
                  //[2012.03.01.목][추가!!!]{------------------------------------------------------
                  //[현재 편집중인 문서] 의 [책갈피] 를 [책갈피 문서] 로 같은 위치에 저장.
                  //[책갈피 대화상자] 는 [현재 편집중인 문서] 만 대상으로 하므로 문서 한개만 처리.
                  //}------------------------------------------------------------------------------

                  if(_bookMark_DialogBox->_enable == true)
                  {
                    _bookMark_DialogBox->_FileSave(filename.c_str());

                  }

              //}

            }

        //}

        //[다른 열린 문서]
        //{
            //[열기]
            //{
                //해당 [임시문서] 를 연다.

                //[임시문서이름] 만들기.(끝에 '~' 문자를 붙여주면 된다.)
                tempfilename = filename + "~";

                //[임시문서] 열기.
                FILE_Open_inBUF(tempfilename, filebuf, &filesize);

                //[정확한 파일 크기 처리]
                //{
                    //[2021.01.15.금][추가]{***************************************
                    //정확한 내용은 이 문서의 같은 날짜로 찾은 첫번째 설명을 참고.
                    //}************************************************************

                    //<filebuf> 에 들어있는 실제 문자열의 길이로 설정(보정)한다.
                    //'\0' 크기 포함------------------------------v
                    _textinfo[i].filesize = STR_Length(filebuf) + 1;

                //}
                
            //}

            //[저장]
            //{
                //[임시문서] 를 해당 [원본문서이름] 으로 저장한다.
                FILE_Save(filename, (unsigned char *)filebuf,
                          //가장 마지막의 '\0' 는 제외하고 저장한다.
                          _textinfo[i].filesize - 1);
            //}

            //[수정처리]
            //{
                //[2007.04.05.목][추가!!!]
                if(i == _textinfo_index)
                {
                  //문서를 저장하였으므로 수정된것이 없음을 기록한다.
                  //[현재문서] 인 경우는 [저장] 확인표시를 해 주어야 하므로 전용 함수를 사용한다.
                  //단, [새문서] 인 경우는 처리하지 않는다.(아직 저장된 것이 아니므로...)
                  if(STR_Match(word, "새문서") != true)
                  {
                    _EDIT_Changed(true, false);
                    _textinfo[i].changed = false;

                  }

                }
                else
                {
                  //[현재문서] 가 아닌 경우는 해당 변수만 수정해 주면 된다.
                  //단, [새문서] 인 경우는 처리하지 않는다.(아직 저장된 것이 아니므로...)
                  if(STR_Match(word, "새문서") != true)
                  {
                    //이미 저장됬다는 것을 알려준다.
                    _textinfo[i].changed = false;

                  }

                }

            //}

        //}

      }

  //}

  //[문서목록 상태반영]
  //{
      //[2007.04.06.금][추가!!!]
      if(editor_top_Form->_list_bmpbtns->_index == d_LIST_up)
      {
        //현재 펼져 있는 경우라면 [문서목록] 에 수정상태를 다시 반영해 주어야 한다.
        editor_top_Form->_Shape();

      }
      
  //}

  //[저장소 삭제]
  //{
      //동적생성한 저장소 공간을 삭제한다.
      if(filebuf != NULL) { delete [] filebuf; filebuf = NULL; }
  //}

}

void __fastcall Teditor_edit_Form::_EDITFILE_SaveAsNowEditFile(void)
{
  //[2007.04.01.일][생성!!!]{-----------------------------------------------------------------
  //현재 열려있는 문서를 다른 이름으로 저장한다.
  //다른이름으로 저장하는 경우는 같은 이름의 문서가 있는 경우도 있고
  //지금문서를 같은 이름으로 다시 저장하는 경우도 있을수 있으므로
  //[덮어쓰기] 와 같은 방식으로 처리 가능하다.

  //[저장] 의 경우는 [새문서] 의 경우만 대화상자를 보여주지만.
  //이 함수는 이미 저장된 문서인지 [새문서] 인지 구분없이 무조건 [대화상자] 를 보여주면 된다.
  //}-----------------------------------------------------------------------------------------

  //[주의!!!]
  //{
      //"다른이름으로저장" 하는 경우는 기본적으로 현재 문서의 [복사본] 을 저장하는것이다.
      //[새문서] -> 지정이름으로 저장 : 현재 문서는 여전히 [새문서] 이다.
      //[새문서] 는 "현재문서저장" 으로 직접 저장하지 않는한 문서목록에는 [새문서] 그대로 있다.
  //}

  //[안전장치]
  //{
      //[2007.03.31.토][추가!!!]
      //현재 열려 있는 문서가 없는 경우는 처리하지 않아야 한다.
      if(_textinfo_count == 0) return;
  //}

  //[다른이름으로 저장]
  //{
      //무조건 대화상자를 보여준다.
      //저장하지 않는 경우는 그냥 종료한다.
      main_Form->file_SaveDialog->Filter = "*.c|*.c|*.h|*.h|*.txt|*.txt|*.gtxt|*.gtxt|*.gasm|*.gasm|*.gcsm|*.gcsm|*.gobj|*.gobj|*.glib|*.glib|*.gob1|*.gob1|*.gtmp|*.gtmp";
      
      if(main_Form->file_SaveDialog->Execute() != true) return;

      //일단 중복여부를 확인한다.
      if(FileExists(main_Form->file_SaveDialog->FileName) == true)
      {
        //중복된 경우는 중복된 이름으로 이미 있는 문서를 지금의 문서로 덮어쓸지
        //묻는 대화상자를 표시한다.
        if(ide_msgbox_Form->_MsgBox_Ok_Cancle(d_MSGBOX_info, //d_MSGBOX_default,
                                              "이미 존재하는 [문서이름] 입니다.\r\n"
                                              "이전 문서를 지금 문서로 덮어쓸까요?") == true)
        {
          //[확인] 이 눌린 경우.

          //[목록에 이미 있는 경우인가?]
          //{
              if(_TEXTINFO_GetIndex_withFILEname(main_Form->file_SaveDialog->FileName) >= 0)
              {
                //[문서목록] 에 이미 있는 경우는 혼란을 방지하기 위하여 저장하지 않으며,
                //사용자에게 경고 문구로 알려준다.
                ide_msgbox_Form->_MsgBox(d_MSGBOX_error,
                                         "이미 열려있는 [문서이름] 으로는 저장할 수 없습니다.\r\n"
                                         "다른 이름으로 다시 저장하십시요.");

                return;

              }
              else
              {
                //[정확한 파일 크기 처리]
                //{
                    //[2021.01.15.금][추가]{***************************************
                    //정확한 내용은 이 문서의 같은 날짜로 찾은 첫번째 설명을 참고.
                    //}************************************************************

                    //편집기에 들어있는 실제 문자열의 길이로 설정(보정)한다.
                    //'\0' 크기 포함-------------------v
                    _filesize = STR_Length(_editbuf) + 1;

                //}

                //이 경우는 [문서목록] 에는 없으므로 다음 처리부에서 그냥 덮어서 저장하도록 놔둔다.
                //[문서목록] 에는 변화가 없고 사용자가 지정한 이름으로 그냥 덮어쓰면 된다.
                FILE_Save(main_Form->file_SaveDialog->FileName, (unsigned char *)_editbuf,
                          //가장 마지막의 '\0' 는 제외하고 저장한다.
                          _filesize - 1);

                //저장했으므로 바로 종료한다.
                return;

              }
          //}
        }
        else
        {
          //[취소] 가 눌린 경우.
          //아무것도 처리하지 않고 종료한다.
          return;

        }

      }
      else
      {
        //이 경우는 현재 존재하지 않는 이름이므로 사용자가 지정한 이름으로 새문서를 하나 만들어 주면 된다.
        //[문서목록] 에는 변화가 없고 단지 현재 문서를 다른이름으로 하나더 만드는 것이다.

        //[정확한 파일 크기 처리]
        //{
            //[2021.01.15.금][추가]{***************************************
            //정확한 내용은 이 문서의 같은 날짜로 찾은 첫번째 설명을 참고.
            //}************************************************************

            //편집기에 들어있는 실제 문자열의 길이로 설정(보정)한다.
            //'\0' 크기 포함-------------------v
            _filesize = STR_Length(_editbuf) + 1;

        //}

        //사용자가 지정한 새로운 이름으로 복제 문서를 하나 생성한다.
        FILE_Save(main_Form->file_SaveDialog->FileName, (unsigned char *)_editbuf,
                  //가장 마지막의 '\0' 는 제외하고 저장한다.
                  _filesize - 1);

        //저장했으므로 바로 종료한다.
        return;

      }
  //}

  return;

}

void __fastcall Teditor_edit_Form::_EDITFILE_NewFile(void)
{
  //[2007.03.28.수][생성!!!]{-----------------------------------------------------------
  //[새문서] 를 하나 만들어 준다.
  //단, 이 문서는 아직 저장된 문서가 아니므로 이미 열려 있는 문서가 있는 경우는
  //이 문서를 저장하고 [편집기] 를 초기화만 시켜주면 된다.([문서열기] 와 비슷한 과정.)
  //
  //[2007.03.31.토][추가!!!]------------------------------------------------------------
  //아무 문서도 열려 있지 않은 상태에서는 [편집기] 는 비활성화 되 있으므로
  //여기서 [새문서] 를 만드는 것이 처음 문서인 경우는 [편집기] 를 활성화 시켜야 한다.
  //
  //[2012.07.05.목][중요설명!!!]--------------------------------------------------------
  //[검증시] 에 [->>>] 버튼으로 자동 검증을 하는 경우는 <*.glib> 문서가 대량으로 열릴수
  //있어 [문서열기제한] 에 걸릴수 있다. 그러나, 이 함수는 [새문서] 를 만들때만 [편집기]
  //안에서 사용되므로 실제 [검증시] 에는 동작하지 않기때문에 이 문제는 고려하지 않는다.
  //
  //[검증시:문서열기제한] 으로 인한 문제는 <Teditor_top_Form::_List_Add()> 함수에서만
  //고려된다.
  //}-----------------------------------------------------------------------------------

  //[VAR]
  //{
      //임시 파일이 존재할 path 를 미리 만들어 놓는다.
      //무조건 *.exe 의 [temp] 폴더에 저장된다.
      AnsiString       newfilename = ExtractFilePath(Application->ExeName) + "temp\\";
      struct TEXTINFO  textinfo;

  //}

  //[관리 범위 확인]
  //{
      //[2010.03.21.일][추가!!!]{-----------------------------------------------------
      //현재 문서 추가시 관리할수 있는 문서의 범위를 초과하는 경우는 추가하지 않는다.
      //해당 [알림글] 을 보여주고 더이상 처리하지 않는다.
      //}-----------------------------------------------------------------------------

      if(_textinfo_count >= _textMaxCount)
      {
        ide_msgbox_Form->_MsgBox
        (d_MSGBOX_error,
         "문서 관리 개수를 초과 하여 더이상 문서를 열수 없습니다."
        );

        //더이상 진행하지 않고 종료한다.
        return;

      }

  //}

  //[초기화]
  //{
      //[2009.04.01.수][추가!!!]{---
      //정보를 초기화 한다.
      //}---------------------------

      _TEXTINFO_Format(&textinfo);

  //}

  //[편집기 활성화]
  //{
      //[2007.03.31.토][추가!!!]
      //현재 문서를 처음 여는 경우는 [편집기] 를 활성화 시킨다.
      if(_textinfo_count == 0)
      {
        //[편집기] 활성화.
        ide_editor_Form->_Enable(true);

        //[2009.04.25.토][추가!!!]
        editor_top_Form->_close_bmpbtns->_Enable(true);
        editor_top_Form->_list_bmpbtns->_Enable(true);

      }

  //}

  //[현재문서처리]
  //{
      //이미 문서가 있는 경우만 처리 되어야 한다.
      if(_textinfo_count > 0)
      {
        //[현재문서저장]
        //{
            //[2007.03.28.수][추가!!!]
            //[새문서] 를 만들기 전에 현재 작업하고 있는 문서를 [임시문서이름] 으로 저장한다.
            _EDITFILE_SaveNowFile_inTEMPfile();
            
        //}

        //[현재 문서 정보 저장]
        //{
            //현재 문서 독립 정보를 저장한다.
            _TEXTINFO_Backup(_textinfo_index);

        //}

      }
      
  //}

  //[새문서 만들기]
  //{
      //일단 현재 버퍼를 완전히 비운다.
      _editbuf[0] = '\0';

      //"새문서.XXX" 형식으로 만든다.(경로 없이 이름만 있다.)
      textinfo.filename = "새문서." + IntToStr(_newfile_count);

      //임시번호를 증가 시킨다.
      _newfile_count++;

      //일단 [새문서] 를 지정 폴더에 저장한다.
      newfilename = newfilename + textinfo.filename;

      //[새문서] 를 일단 저장한다.
      FILE_Save(newfilename, (unsigned char *)_editbuf,
                //[새문서] 는 크기가 없다.
                0);
  //}

  //[추가]
  //{
      //현재 문서의 index 를 지정한다.
      _textinfo_index = _textinfo_count;

      _TEXTINFO_Add(&textinfo);

  //}

  //[주의!!!][2007.04.07.토][수정!!!]{------------------------------------
  //이 위치에 [다시그리기] 를 하는 경우는 [문서목록] 이 펼쳐져 있는 경우,
  //문서수정내용 (*) 표시가 나올수 있다.
  //아래 _EDITFILE_Open() 함수에서 완전히 내용이 초기화 된후 그려지도록
  //맨 마지막에 배치한다.
  //}---------------------------------------------------------------------

  //[문서 열기]
  //{
      //현재 지정된 문서를 열어서 [편집기] 표시해준다.
      //이는 "처음 문서를 여는 경우" 이다.
      _EDITFILE_Open(_textinfo[_textinfo_index].filename);

      //[정확한 파일 크기 처리]
      //{
          //[2021.01.15.금][추가]{***************************************
          //정확한 내용은 이 문서의 같은 날짜로 찾은 첫번째 설명을 참고.
          //}************************************************************

          //이 문서는 [새문서] 로 위의 "_TEXTINFO_Format(&textinfo);" 부분에서
          //초기화(0) 된 크기를 그대로 유지하면 된다.

      //}

  //}

  //[다시 그리기]
  //{
      //[2007.04.07.토][수정!!!]
      //내용이 수정되었으므로 제목줄을 다시 그려준다.
      editor_top_Form->_Shape();

  //}

  return;

}

void __fastcall Teditor_edit_Form::_EditBuf_Clear(void)
{
  //[2006.12.17.일][생성!!!]{-------------------------------------
  //[저장소] 를 완전히 비운다.
  //표시할 내용이 없으므로 [편집기] 내용도 다시 그려 주어야 한다.
  //}-------------------------------------------------------------

  //[저장소 비우기]
  //{
      _editbuf[0] = '\0';
  //}

  //[문서 출력]
  //{
      //[저장소] 가 비워졌으므로 [편집기] 창을 다시 그려서 비워 주어야 한다.
      _EditBuf_Text();
  //}

  return;

}

void __fastcall Teditor_edit_Form::_BACKBMP_BrightEnable(bool  pENABLE)
{
  //[2007.03.31.토][생성!!!]{-------------------------
  //[편집기] 배경을 밖게 하거나 원본 그대로 보여준다.
  //}-------------------------------------------------

  switch(pENABLE)
  {
    case true :
    {
      //그림을 밝기 조정하여 표시한다.

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

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

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

    } break;

    case false :
    {
      //그림을 밝기 처리 없이 그대로 표시한다.

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

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

    } break;

  }

  //[다시 그리기]
  //{
      //다시 그리는 것으로 반영한다.
      _Shape();
  //}

  return;

}

//[편집관련]--------------------------------------------------------------------

void __fastcall Teditor_edit_Form::_EDIT_Init(void)
{
  //[2007.01.18.목][생성!!!]{-------------------------------------------------------------
  //열려 있던 문서가 다시 전부 닫히는 경우 이 함수를 사용하여 다시 전부 초기화 해야 한다.
  //
  //[2012.04.29.일][수정!!!]--------------------------------------------------------------
  //[2012.06.09.토][추가!!!]--------------------------------------------------------------
  //}-------------------------------------------------------------------------------------

  //[edit 변수]
  //{
      //내용이 아무것도 없는 것이다.
      _editbuf[0] = '\0';
      _tempbuf[0] = '\0';

      //[문서 기준 원점]
      //{
          _font.margin_size = d_gutter_width + 2 - 1;
          _text_org_x = _font.margin_size;
          _text_org_y = 2;
      //}

      _moonja       = 0;
      _ime_TkorFeng = false;

      _caret_x = 0;
      _caret_y = 0;

      //[관리변수]
      //{
          //[입력지정자] 가 위치해야 하므로 행은 무조건 한개는 있어야 한다.
          _linecount = 1;

          //처음에는 문서가 없다. (단, '\0' 이 있으므로 1 로 설정한다.)
          _filesize = 1;

          _linestartindex = 0;
          _lineendindex   = 0;

          _linetop_linenumber = 0;
          _linetop_startindex = 0;

          _caretindex      = 0;
          _caretindexwidth = 0;

          //[단어 구간 정보]
          //{
              //[2012.05.24.목][추가!!!]
              _wordStartIndex = 0;
              _wordEndIndex   = 0;

          //}

          //[세로줄]
          //{
              //[2012.06.09.토][추가!!!]
              _vLineEn = false;
              _vLineX  = -1;
              //처음에는 항상 <true> 로 함수동작 상태로 설정.
              _sw_VLine = true;

          //}

          _row = 0;
          _col = 0;

          //[2007.04.05.목][추가!!!]
          //_changed = false;
          _EDIT_Changed(true, false);

          //[2009.03.31.화][추가!!!]
          //읽기전용 속성 초기화(기본은 수정 가능한 상태).
          _readOnly = false;

          //[2009.04.25.토][추가!!!]
          _readOnlyAll = false;

          //[2009.03.31.화][추가!!!]
          //기본적으로 [색동문자] 가 적용되지 않는 일반 문서로 설정한다.
          _fileKind = d_Editor_FileKind_default;

          //[문서 수정 이력 초기화]{---
          //[2009.05.03.일]
          History_Init();
          //}--------------------------

          //[문서 용도 종류]
          //{
              //[2022.06.27.월][추가]
              _fileUseKind = d_Editor_fileUseKind_Default;

          //}

      //}

      //[정지점 초기화]
      //{
          //[2007.04.13.금][추가!!!]
          _BREAKPOINT_Init(&_breakpoint);
      //}

      //[문서 정보 관리]
      //{
          _textinfo_count  = 0;
          //처음에는 선택된 문서가 없다.(아무 문서도 열려 있지 않은 경우.)
          _textinfo_index  = -1;
      //}

      //기본적으로 문서는 출력되어야 한다.
      _editbuf_text_on  = true;
      _edit_caretpos_on = true;
      _edit_paste_ing   = false;
      _editbuf_text_no  = false;

      //[2009.05.07.목][추가!!!]
      _editBuf_Text_No_Select = false;

      //[마우스] 는 기본적으로 눌린 상태는 아니다.
      _mouse_down  = false;
      _shift_down  = false;
      _scroll_ing  = false;

  //}

  //[선택영역]
  //{
      //[2007.03.17.토][추가!!!]
      //[선택영역] 을 초기화 한다.
      //둘중 하나라도 -1 인 경우는 [선택영역] 이 존재하지 않는것이다.
      _Select_CaretIndex(&_select_start, -1); //_select_start.caret_index = -1;
      _select_start.caret_x     = 0;
      _select_start.caret_y     = 0;

      _Select_CaretIndex(&_select_end, -1); //_select_end.caret_index   = -1;
      _select_end.caret_x       = 0;
      _select_end.caret_y       = 0;

      //기본적으로 [선택영역] 은 형성되지 않은 상태이다.
      _select_ing        = false;
  //}

  //[캐럿생성]
  //{
      //[2012.04.29.일][수정!!!]{------------------------------------
      //이제까지 왜 [입력지정자] 를 여기서 재생성 했는지 알수 없으나
      //재생성 할 필요가 없으므로 주석으로 처리한다.
      //}------------------------------------------------------------

      /*_caret         = new Tgui_caret_Form(this);
      //_caret->Parent = this;

      //[기본설정]
      //{
          _caret->Width  = 2;
          _caret->Height = 12;
          _caret->Left   = _font.margin_size;
          _caret->Top    = 2;
      //}
      */

      //[입력지정자] 의 기본 위치를 지정한다.
      _EDIT_CaretPos(_caret_x, _caret_y);

  //}

  //[부가 처리]
  //{
      //문서양에 맞게 다시 스크롤을 설정한다.
      //완전 초기화 상태이므로 아무 내용도 없는 것이다.
      _Scroll_Set();

  //}

  //[문서 출력]
  //{
      //불러들인 문서를 [편집기] 에 출력하여 보여준다.
      _EditBuf_Text();

  //}

}

void __fastcall Teditor_edit_Form::_EDIT_TextOut(char  pText[])
{
  //[2007.10.09.화][생성!!!]{----------------------
  //전달받은 문자열을 출력한다.
  //단순히 문자열을 출력하는 경우에 사용한다.
  //Memo->Text() 함수와 같은 용도로 사용하면 된다.
  //}----------------------------------------------

  //[초기화]
  //{
      //문자열 할당.
      STR_Assign(_editbuf, pText);

      //현재 [문서크기] 를 기록해 놓는다.
      //'\0' 크기까지 기록한다.
      _filesize = strlen(pText) + 1;
      //}

      //[관리 정보 초기화][주의!!!]
      //{
          //-------------------------------------------------------------------
          //새로 열 [문서] 의 [문서정보] 를 완전히 초기화 한다.
          //_linecount 도 아래 함수에서 초기화 되므로 먼저 처리해 주어야 한다.
          _ROOT_TEXTINFO_Init();
          //-------------------------------------------------------------------
      //}

      //[문서 총 행수 구하기]
      //{
          //이미 열어 놓은 문서의 총 행수를 구하여 전역변수에 기록해 놓는다.
          _linecount = STR_Get_LineCount(_editbuf);
      //}

      //[부가 처리]
      //{
          //문서양에 맞게 다시 스크롤을 설정한다.
          //[문서] 를 처음 연 것이므로 [스크롤] 을 전부 다시 설정한다.
          _Scroll_Set();
      //}

      //[문서 출력]
      //{
          //불러들인 문서를 [편집기] 에 출력하여 보여준다.
          _EditBuf_Text();
      //}

  //}

  return;

}

bool __fastcall Teditor_edit_Form::_EDIT_IS_ImeHangul(void)
{
  //[2006.12.19.화][생성!!!]{------------
  //현재 IME 가 [한글/영문] 인지 구한다.
  //한글 : true.
  //영문 : false.
  //}------------------------------------

  //[VAR]
  //{
      HIMC   mode;
      DWORD  conversion, sentence;
  //}

  mode = ImmGetContext(this->Handle);

  ImmGetConversionStatus(mode, &conversion, &sentence);

  //한글(true)/영문(false) 를 반환한다.
  return (conversion == IME_CMODE_HANGEUL);

}

void __fastcall Teditor_edit_Form::_EDIT_Change_ImeMode(void)
{
  //[2006.12.19.화][생성!!!]{----------------------------------------------------------
  //현재 ime-mode 를 전환한다.
  //실제 ime-mode 는 OS 자체에서 자동으로 전환되므로 여기서 추가로 처리할 필요는 없다.
  //}----------------------------------------------------------------------------------

  //[VAR]
  //{
      HIMC   mode;
  //}

  mode = ImmGetContext(this->Handle);

  if (_EDIT_IS_ImeHangul() == true)
  {
    //[한글] => [영문]
    ImmSetConversionStatus(mode, IME_CMODE_ALPHANUMERIC, IME_CMODE_ALPHANUMERIC);

  }
  else
  {
    //[영문] => [한글]
    ImmSetConversionStatus(mode, IME_CMODE_HANGEUL, IME_CMODE_HANGEUL);

  }

  return;

}

void __fastcall Teditor_edit_Form::_EDIT_Changed(bool  pALWAYS,
                                                 bool  pCHANGED)
{
  //[2007.04.05.목][생성!!!]{---------------------------------------------------------
  //현재 편집중인 문서가 변경되는 경우를 처리한다.
  //수정되었다는 것을 기록하고 이 문서가 수정되었다는 것을 해당 정보란에 표시한다.
  //단, 문자가 계속 입력될때 처리 속도가 떨어지는 것을 막기 위하여 반드시 이전 상태와
  //다른 경우만 다시 그려 주어야 한다.
  //
  //[2007.04.07.토][수정!!!]----------------------------------------------------------
  //문서를 여는 경우나 저장하는 경우는 무조건 다시 그려주는 것이 정확하므로,
  //pALWAYS == true 의 경우는 무조건 다시 그려주는 것으로 수정한다.
  //
  //[2009.06.02.화][추가!!!]----------------------------------------------------------
  //수정된 경우는 {/* ... */} 주석문 정보를 얻도록 알려준다.
  //}---------------------------------------------------------------------------------

  //[VAR]
  //{
      bool  change = false;

  //}

  //[유효확인]
  //{
      //[2007.10.01.월][추가!!!]
      //이 편집기가 동작 가능한 상태일 경우만 처리한다.
      if(ide_editor_Form != NULL)
      {
        if(ide_editor_Form->Enabled != true) return;

      }

  //}

  //[상태처리]
  //{
      //[변화 검사]
      //{
          //값이 변했는지를 기록한다.
          if(_changed != pCHANGED) change = true;

      //}

      _changed                           = pCHANGED;
      _textinfo[_textinfo_index].changed = pCHANGED;

  //}

  //[상태표시]
  //{
      //[수정] 상태를 표시하는 부분에 해당 처리를 수행한다.
      if(editor_info_Form != NULL)
      {
        //[문서목록] 이 펼쳐져 있고 변화가 있는 경우만 처리한다.
        if((change == true) || (pALWAYS == true))
        {
          //수정 상태 여부를 해당 알림란에 표시해준다.
          editor_info_Form->_Changed(pCHANGED);

          //[문서목록] 이 펼쳐져 있는 경우는 해당 내용을 반영해야 한다.
          if(editor_top_Form->_list_bmpbtns->_index == d_LIST_up)
          {
            //[2007.04.06.금][추가!!!]
            //다시 그리는 것으로 자동 반영된다.
            editor_top_Form->_Shape();

          }

        }

      }

  //}

}

bool __fastcall Teditor_edit_Form::_EDIT_SaveCheckChanged_whenCloseThis(int  pLISTindex)
{
  //[2007.04.06.금]{-------------------------------------------------------------
  //[문서목록] 에서 pLISTindex 상의 문서가 수정된 경우는 이 문서가 닫힐때
  //사용자에게 이 사실을 알리고 저장후 닫을지를 물어야 한다.
  //"확인" 을 누른 경우 여기서 직접 저장하지는 않고 사용자가 직접 저장하게 한다.
  //"확인" : true 반환.
  //"취소" : false 반환. (이 경우는 문서가 수정된 것이 없는 경우도 해당한다.)
  //}----------------------------------------------------------------------------

  //[VAR]
  //{
      AnsiString  msgstr;
  //}

  //지정 문서가 수정된 상태인 경우만 처리한다.
  if(_textinfo[pLISTindex].changed == true)
  {
    //출력할 문자열을 합성한다.
    msgstr = "\"" + _textinfo[pLISTindex].filename + "\"\r\n"
             "는 아직 저장되지 않은 문서입니다.\r\n"
             "그냥 종료하시겠습니까?";

    if(ide_msgbox_Form->_MsgBox_Ok_Cancle(d_MSGBOX_info, msgstr.c_str()) != true)
    {
      //사용자가 직접 저장하겠다는 것이다.
      return(true);

    }

  }

  //저장하지 않고 그냥 종료해도 상관없다는 경우.
  return(false);

}

bool __fastcall Teditor_edit_Form::_EDIT_SaveCheckChanged_whenCloseAll(void)
{
  //[2007.04.06.금]{--------------------------------------------------------
  //[통합개발환경] 이 종료되는 경우 열려 있는 문서중 저장되있지 않은 문서를
  //나열하여 보여주고 이들중 하나라도 저장해야 하는 경우는 종료하지 않고
  //다시 사용자가 저장할수 있게 만든다.
  //}-----------------------------------------------------------------------

  //[VAR]
  //{
      AnsiString  msgstr = "";
      int         i;
  //}

  for(i = 0; i < _textinfo_count; i++)
  {
    //수정된 상태인 문서이름만 나열한다.
    if(_textinfo[i].changed == true)
    {
      msgstr = msgstr + "\"" + _textinfo[i].filename + "\"\r\n";

    }

  }

  //아직 저장되지 않은 문서가 있는 경우만 처리한다.
  if(msgstr != "")
  {
    //나머지 출력할 문자열을 합성한다.
    msgstr = msgstr +
             "는 아직 저장되지 않은 문서들입니다.\r\n"
             "그냥 종료하시겠습니까?";

    if(ide_msgbox_Form->_MsgBox_Ok_Cancle(d_MSGBOX_info, msgstr.c_str()) != true)
    {
      //사용자가 직접 저장하겠다는 것이다.
      return(true);

    }

  }

  //저장하지 않고 그냥 종료해도 상관 없는 경우.
  return(false);

}

void __fastcall Teditor_edit_Form::_EDIT_Get_TextOrigin(void)
{
  //[2006.12.23.토][생성!!!]{-------------------------------------------------------
  //문서 기준 원점을 얻는다.
  //[스크롤] 되는 경우는 [문서원점] 이 수정되므로 항상 이 함수로 다시 [문서원점] 을
  //설정해 주어야 한다.
  //}-------------------------------------------------------------------------------

  //[VAR]
  //{
      int  scroll_v_position;
      int  scroll_h_position;
  //}

  //[스크롤정보얻기]
  //{
      //폼이 생성되 있는 경우만 처리한다.
      if(ide_editor_Form == NULL) return;

      scroll_v_position = ide_editor_Form->_scroll_v_Form->_position;
      scroll_h_position = ide_editor_Form->_scroll_h_Form->_position;
  //}

  //[좌표수정]
  //{
      _text_org_x = (-1) * scroll_h_position * _word_width  + d_gutter_width + 2 - 1;
      _text_org_y = (-1) * scroll_v_position * _line_height + 2;
  //}

  return;

}

void __fastcall Teditor_edit_Form::_EDIT_CaretPos(int  pX,
                                                  int  pY)
{
  //[2006.12.23.토][생성!!!]{-------------------------------------------------
  //[입력지정자] 의 위치를 지정한다.
  //이 위치는 [문서원점] 을 원점으로한 위치가 된다.
  //
  //[2007.02.11.일][수정!!!]--------------------------------------------------
  //[입력지정자] 가 이동하는 경우 [선택영역] 이 해제 될수 있다.
  //그러나, 이미 [선택영역] 이 존재하는 경우 [줄이동] 시에는 선택영역을
  //해제하지 않아야 한다.
  //
  //[2007.03.16.금][참고!!!]--------------------------------------------------
  //이 함수는 [입력지정자] 위치만 수정할 뿐 자체적으로 _EditBuf_Text()
  //함수로 다시 그려지지 않는다. 단, [선택영역] 이 해제되는 경우는
  //_EditBuf_Text() 로 다시 그려서 해제된것을 반영해 주어야 한다.
  //
  //[2007.04.08.일][수정!!!]--------------------------------------------------
  //[왼쪽무효영역] 에 [입력지정자] 가 위치하는 경우는 보이지 않게 해야 한다.
  //
  //[2009.05.04.월][중요수정!!!]----------------------------------------------
  //이전에 이 함수 내부적으로 <_col> 이 계산되지 않으므로 [열] 이 제대로 반영
  //되지 않는 문제가 있어서 _Edit_Col() 함수로 [열] 은 별도 반영하는 것으로
  //수정하였다.
  //
  //[2012.05.23.수][수정!!!]--------------------------------------------------
  //[2012.05.24.목][수정!!!]--------------------------------------------------
  //[2012.06.01.금][수정!!!]--------------------------------------------------
  //[2012.06.09.토][수정!!!]--------------------------------------------------
  //}-------------------------------------------------------------------------

  //[VAR]
  //{
      int  row = 0;
      int  col = 0;

  //}

//[2012.05.31.목][임시문장]
//msg_msg_Form->_PrintAddLine(0, "_EDIT_CaretPos");

  //처리를 요하는 경우만 처리한다.
  if(_edit_caretpos_on != true) return;

  //[위치지정]
  //{
      //[2007.04.08.일][수정!!!]
      //[왼쪽무효영역] 에 [입력지정자] 가 위치하는 경우는 보이지 않게 해야 한다.
      if(((_text_org_x - d_gutter_width) + _caret_x) < 0)
      {
        //[왼쪽무효영역(검증판)] 을 벗어나는 경우는 [입력지정자] 를 보이지 않게 만들어야 한다.
        //이 영역은 일반적으로 "gutter" 영역으로 불린다.
        _caret->_Hide();

      }
      else
      {
        //실제 위치를 [문서원점] 에 대한 좌표로 환산하여 지정한다.
        //자동으로 다시 [입력지정자] 가 보여지므로 굳이 _Show() 를 호출하지 않아도 된다.
        _caret->_Position(_text_org_x + pX, _text_org_y + pY);

      }

  //}

  //[행/열 계산]
  //{
      //[입력지정자] 가 위치한 [행/열] 값을 구하여 정보 표시 위치에 표시한다.

      //[행 구하기]
      //{
          //행은 바로 구할수 있으므로 여기서 전역 변수에 저장까지 수행한다.
          _row = _caret_y / _line_height;
          row  = _row;
      //}

      //[열 구하기]
      //{
          //[<열> 위치 구하기/표시][2009.05.04.월][추가!!!]{---
          //이 함수 내부적으로 자동으로 _col 이 구해진다.
          _Edit_Col(_caretindex);
          //}--------------------------------------------------

          col  = _col;

      //}

      //[행/열 표시]
      //{
          if(editor_info_Form != NULL)
          {
            //[행/열] 표시.
            editor_info_Form->_Row_Col(row, col);

          }
      //}
  //}

  //[선택영역해제]
  //{
      //[2007.02.11.일][수정!!!]{------------------------
      //[줄이동] 시에는 [선택영역] 은 그대로 유지시킨다.
      //}------------------------------------------------

      if(_scroll_ing == false)
      {
        //[2012.06.09.토][중요수정!!!]{------------------------------------------
        //[선택영역] 검사조건을 [둘다 <-1> 이 아닌 경우] 로 변경하고
        //같은 값인 경우역시 [선택영역] 이 아닌 것으로 추가.
        //이전까지 [둘중 한개만 <-1> 인 경우] 로 처리한 바람에
        //계속 <_EditBuf_Text()> 가 실행되어 문자입력시 처리 속도가 너무 느렸다.
        //<_SELECT_Get_StartEndIndex()> 함수가 가장 정확한 것이므로 이 안의
        //조건으로 새로 수정한다.
        //}----------------------------------------------------------------------

        //[2012.06.09.토][주석처리!!!]
        //if((_shift_down == false) && (_mouse_down == false) &&
        //   ((_select_start.caret_index >= 0) || (_select_end.caret_index >= 0)))
        //[2012.06.09.토][추가!!!]
        if((_shift_down == false) && (_mouse_down == false) &&
           //둘다 <-1> 이 아닌 경우만 [선택영역] 이 유효한 것으로 본다.
           //여기서는 일단 둘중 하나만 해당되면 통과.
           //이 내부에서 둘다 해당하는 경우만 [다시 그리기] 하는 것으로 수정.
           //이는 [화면지정자] 를 찍을때 [선택영역:시작위치] 가 항상 기록되기 때문에
           //<Shift> 를 누르자 마자 현재 [입력 지정자] 위치가 [선택영역:끝위치] 로
           //지정되어 [선탱영역] 이 발생하는 것을 막기 위한것.
           //이 경우는 일단 [선택영역] 을 [해제] 하고 시작해야 한다.
           ((_select_start.caret_index >= 0) || (_select_end.caret_index >= 0)) &&
           //선택값이 있더라도 두 값이 같은 경우는 [선택영역] 은 존재하지 않는 것.
           (_select_start.caret_index != _select_end.caret_index))
        {
          //[!]{--------------------------------------------------------
          //[선택영역] 정보 초기화.
          //
          //[2012.06.09.토][중요수정!!!]--------------------------------
          //[선택영역] 이 완전히 존재하는 경우와 다른 경우를 구분 처리.
          //}-----------------------------------------------------------

          if((_select_start.caret_index >= 0) && (_select_end.caret_index >= 0))
          {
            //[중요!!!]{------------------------------------------------
            //[다시 그리기] 시에는 반드시 [둘다 해당] 하는 경우만 처리.
            //}---------------------------------------------------------

            _Select_CaretIndex(&_select_start, -1); //_select_start.caret_index = -1;
            _select_start.caret_x     = 0;
            _select_start.caret_y     = 0;

            _Select_CaretIndex(&_select_end, -1); //_select_end.caret_index   = -1;
            _select_end.caret_x       = 0;
            _select_end.caret_y       = 0;

            _select_ing               = false;

            //[선택영역] 해제 반영.
            _EditBuf_Text();

          }
          else
          {
            //[!]{---------------------------------------------------------------------
            //[선택영역] 만 [해제] 하고 다시 그리지는 않는다.
            //이 경우는 [화면지정자] 로 찍은 경우 [선택영역:시작위치] 만 기록된 경우로
            //현재 [선택영역] 이 존재하는 것은 아니기 때문에 [해제] 만 하면 된다.
            //}------------------------------------------------------------------------

            _Select_CaretIndex(&_select_start, -1); //_select_start.caret_index = -1;
            _select_start.caret_x     = 0;
            _select_start.caret_y     = 0;

            _Select_CaretIndex(&_select_end, -1); //_select_end.caret_index   = -1;
            _select_end.caret_x       = 0;
            _select_end.caret_y       = 0;

            _select_ing               = false;

          }

        }

      }

  //}
  
  //[실시간 선언 정보판 관련]
  //{
      //[단어 구간 정보 추출]
      //{
          //[2012.05.24.목][추가!!!]{---------------------------------------------
          //실시간으로 [입력지정자] 가 위치한 [단어] 의 [시작/끝:위치] 를 관리.
          //
          //[2012.06.01.금][설명!!!]----------------------------------------------
          //<_EDITBUF_LINE_Out()> 에서 [실시간 선언 정보판:대상단어] 를 지정할때
          //<_wordStartIndex/_wordEndIndex> 정보를 사용하므로 항상 수집해 놓는다.
          //}---------------------------------------------------------------------

          STR_Get_WordBound(_editbuf, _filesize, _caretindex,
                            &_wordStartIndex,
                            &_wordEndIndex);

      //}

      //[실시간 선언 정보판 감추기]
      //{
          //[2012.05.24.목][추가!!!]{----------------------------
          //[실시간 선언 정보판] 이 보이는 경우만 처리하고
          //처리후 반드시 [단어지정] 을 위하여 [입력지정자] 가
          //위치한행만 다시 그린다.
          //
          //더불어, <info_tree_Form->_AutoHide_WordBound()> 에서
          //기존 [단어 구간] 을 벗어난 경우는 자동으로 감춰진다.
          //}----------------------------------------------------

          if(info_tree_Form != NULL)
          {
            if((info_tree_Form->Visible == true) &&
               //[2012.06.01.금][추가!!!]
               //<_AutoHide_WordBound()> 함수 사용 허가상태만 처리.
               (info_tree_Form->_sw_AutoHide_WordBound == true))
            {
              //현재 [단어 구간 정보] 전달.
              info_tree_Form->_AutoHide_WordBound(_wordStartIndex, _wordEndIndex);

              //현재 [입력지정자] 가 위치한 행만 다시 그린다.
              _EditBuf_LineText(_row, false);

            }

          }

      //}
      
  //}    

}

void __fastcall Teditor_edit_Form::_Edit_Col(int   pCaretindex)
{
  //[2009.05.04.월][생성!!!]{-------------------------------------------------------------------------
  //현재 [입력지정자] 의 정보를 바탕으로 <_col> 값을 구하고 직접 해당 정보를
  //표시란에 표시해 주는것 까지 수행한다.
  //이는 실제 _EDIT_CaretPos() 함수안에서는 <_col> 값이 구해지지 않고 이미
  //있는 값만 사용하게 되므로 [선택영역 삭제] 등의 경우등은 제대로 [열] 이 계산
  //되지 못하여 정확한 위치가 표시되지 않는 무제가 발생하는 것을 금일 발견하였다.
  //따라서, 이를 수정하고자 이 함수를 만들어 별도 처리한다.
  //
  //[2009.05.25.월][중요수정!!!]----------------------------------------------------------------------
  //[편집기] 에서 잘라내기, 붙이기, 선택영역의 삭제등의 처리 후 <Key-Up>, <Key-Down> 등을
  //사용하는 경우 [입력지정자] 의 위치가 정확하지 않았는데 알고보니 아래와 같은 문제가 있었다.
  //(1) 선택영역의 잘라내기 삭제등의 경우 <_caretindex> 는 자동으로 [선택영역] 시작 위치로
  //    수정되어 [삭제] 시에도 항상 정확한 위치를 갖게 된다 <_caretindexwidth> 는 수정하지 않아서
  //    이전 그대로의 위치를 갖게 되있었다.
  //
  //(2) 이 경우 KeyUp(), KeyDown() 의 처리시 _CARETINDEXWIDTH_CaretIndex() 함수로 다시
  //    <_caretindex> 를 구하게 되는데 <_caretindexwidth> 가 수정되지 않은 이전 값이므로
  //    이전의 <_caretindex> 의 위치에 [입력지정자] 가 놓이게 된 것이다.
  //
  //(3) 따라서 (1) 의 경우 무조건 <_caretindexwidth> 도 같이 수정해 주어야 하는데
  //    모든 [입력지정자] 의 위치 수정에 대하여 _EDIT_CaretPos() 함수가 호출되는데
  //    _EDIT_CaretPos() 함수 안에서 바로 현재 함수가 다시 호출되게 되므로 이 함수안에서
  //    반드시 _CARETINDEX_CaretIndexWidth() 함수로 <_caretindexwidth> 를 무조건 구하는 것으로 한다.
  //    이전에는 NULL 을 사용하여 처리하지 않았으나 금일 무조건 값을 구하여 저장하는 것으로 수정한다.
  //}-------------------------------------------------------------------------------------------------

  //[VAR]
  //{
      int  lineStartIndex;

  //}

  //[행 시작 위치 얻기]
  //{
      //현재 지정위치가 있는 행의 [시작위치] 를 얻는다.
      STR_Get_ThisLineStartIndex(_editbuf, pCaretindex, &lineStartIndex);

  //}

  //[열정보얻기]
  //{
      //<_col> 정보는 [열] 표시를 위하여만 사용되므로 그냥 여기서 구해버린다.

      //[2009.05.25.월][수정!!!]
      //무조건 <_caretindexwidth> 를 구하는 것으로 수정 한다.----------v
      _CARETINDEX_CaretIndexWidth(lineStartIndex, pCaretindex, &_caretindexwidth, &_col);

  //}

  //[행/열 표시]
  //{
      if(editor_info_Form != NULL)
      {
        //[행/열] 표시.
        editor_info_Form->_Row_Col(_row, _col);

      }

  //}

  return;

}

void __fastcall Teditor_edit_Form::_EDIT_Get_Kor_Eng_Moonja_Width(void)
{
  //[2006.12.27.수][생성!!!]{------------------------------------------------------------
  //현재 [편집기] 는 [고정폭 글꼴] 을 사용하고 있으므로 [한글/영문] 각각 대표하는 문자의
  //[문자폭] 을 한개씩만 대표값으로 구해 놓는다.
  //이는 [입력지정자] 위치 산출등 여러 곳에 사용되는 중요한 값이다.
  //이 함수는 [글꼴] 을 생성한 다음에 한번만 호출하면 된다.
  //덤으로 _line_height 값도 같이 얻는다.
  //
  //직접 문자를 출력하나 [편집기] 배경이 지워지기 전에 이 함수를 사용하면 출력된 문자는
  //배경을 그릴때 다 지워 지므로 상관없다.
  //}------------------------------------------------------------------------------------

  //[한글] 대표문자 출력.
  FONT_Out_Moonja(_bmp_, &_font, 0, 0, IDE_COLOR_1, IDE_COLOR_2, false, '김', &_font_kor_width, &_line_height);

  //[영문] 대표문자 출력.
  FONT_Out_Moonja(_bmp_, &_font, 0, 0, IDE_COLOR_1, IDE_COLOR_2, false, 'A', &_font_eng_width, &_line_height);

  return;

}

void __fastcall Teditor_edit_Form::_EDIT_V_Scroll(void)
{
  //[2006.12.29.금][생성!!!]{-------------------------------------------------
  //이 문서가 [수직 스크롤] 되는 경우 처리를 수행한다.
  //
  //[2007.02.10.토][수정!!!]--------------------------------------------------
  //[선택영역] 이 생성중인 경우는 어차피 [선택영역] 처리부에서 자동으로
  //_EditBuf_Text() 함수를 사용하여 다시 그리게 되므로 중복되는 것을 막기
  //위하여 여기서는 처리하지 않는다.
  //이는 [선택영역] 을 만들어 가는 과정에서 [편집기] 영역을 벗어나면 자동으로
  //[줄이동] 을 하게 되는데 이때 [수직줄이동] 의 경우 이 함수가 호출되므로
  //여기서 특별히 처리하는 것이다.
  //
  //[2007.02.11.일][수정!!!]--------------------------------------------------
  //[줄이동] 중인 경우는 _scroll_ing == true 로 설정하여 _EDIT_CaretPos()
  //함수안에서 [선택영역] 이 해제되는 것을 막아야 한다.
  //
  //[2012.04.15.일][수정!!!]--------------------------------------------------
  //[2012.06.12.화][추가!!!]--------------------------------------------------
  //}-------------------------------------------------------------------------

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

      //[2012.06.12.화][추가!!!]
      //<_CommentBlock_Info()> 의 결과를 보관.
      bool   cmtBlkChanged = false;

  //}

  //[선언정보판 감추기]
  //{
      //[2012.04.15.일][추가!!!]
      if(info_tree_Form != NULL)
      {
        if(info_tree_Form->Visible == true) { info_tree_Form->Visible = false; }

      }

  //}
  
  //[문서 출력 원점 얻기]
  //{
      //[문서] 를 출력할 기준 원점을 구한다.
      //이미 [스크롤] 된 상태이므로 이 시점에서 [문서원점] 을 구해야 한다.
      _EDIT_Get_TextOrigin();

  //}

  //[편집창 윗 행]
  //{
      //[편집창] 윗 행은 다른 처리시 속도 향상을 위하여(계속 행을 구하는 것은 많은 시간이 소요된다.)
      //계속 값을 수정해 주어 정확한 현재 값을 가지도록 한다.

      //[안전장치]{-----------------------
      if(ide_editor_Form == NULL) return;
      //}---------------------------------

      //변화행 수를 얻는다.
      count = ide_editor_Form->_scroll_v_Form->_position - _linetop_linenumber;

      //[편집기] 상에서 보여지는 가장윗줄의 [행 번호] 를 구한다.
      //행단위로 [스크롤] 하므로 position 값은 직접적으로 보이는 가장 윗 [행 번호] 와 일치한다.
      _linetop_linenumber = ide_editor_Form->_scroll_v_Form->_position;

      if(count >= 0)
      {
        //다음행으로 [스크롤] 한 경우.

        for(i = 0; i < count; i++)
        {
          //계속 다음행을 처리하는 것으로 값을 구한다.
          STR_Get_NextLineStartIndex(_editbuf, _linetop_startindex, &_linetop_startindex);

        }

      }
      else
      {
        //이전행으로 [스크롤] 한 경우.

        //일단 양수로 바꿔준다.
        count = (-1) * count;

        for(i = 0; i < count; i++)
        {
          //계속 이전행을 처리하는 것으로 값을 구한다.
          STR_Get_BeforeLineStartIndex(_editbuf, _linetop_startindex, &_linetop_startindex);

        }

      }
  //}

  //[검증창 동기화]
  //{
      _DEBUG_Scroll(ide_editor_Form->_scroll_v_Form->_position);

  //}

  //[묶음주석 정보 수집]
  //{
      //[2012.06.12.화][추가!!!]{--------------------------------------------
      //금일 [묶음주석:정보] 는 항상 [보이는 영역] 을 기준으로 처리하므로
      //[보이는 영역] 의 [수정] 이 이루어 지는 [수직 줄이동] 시에 도 반드시
      //정보를 수집해야 한다.
      //단, [수직 줄이동] 할수 있다는 것은 이미 [문서] 가 열려 있다는 의미고
      //[문서 열기] 시에 항상 [문서 처음부터] 정보 수집을 하기 때문에 여기는
      //[부분수집] 으로 처리.
      //}--------------------------------------------------------------------

      if(count <= ((this->Height - editor_info_Form->Height) / _line_height))
      {
        //[2012.06.13.수][수정!!!]{---------------------------------------------
        //[편집기:높이] 단위(PageUp/Dowm 크기와 동일) [이하] 로 이동하는 경우는
        //반드시 [보이는 영역] 을 거치게 되므로 [부분수집] 만 하면 된다.
        //}---------------------------------------------------------------------

        //부분정보 수집--------------------v
        cmtBlkChanged = _CommentBlock_Info(true);

      }
      else
      {
        //[2012.06.13.수][수정!!!]{------------------------------------------------------
        //[편집기:높이] 단위(PageUp/Dowm 크기와 동일) 를 [초과] 하여 이동하는 경우는
        //[보이는 영역] 을 건너뛰게 되는 부분이 발생하여 제대로 [묶음주석] 정보를
        //수집하지 못하고 놓치는 부분이 발생하므로 이 경우는 [처음부터] 검사한다.
        //단, <Ctrl+Home/End> 나 [순간 이동식 수직 줄이동], [쪽] 단위를 넘는
        //문자열 [붙이기/잘라내기] 등이 해당한다.
        //[빈도수] 가 높지 않기 때문에 [처음부터] 처리해도 [편집시간] 에 큰 영향이 없다.
        //}------------------------------------------------------------------------------

        //전체정보 수집--------------------v
        cmtBlkChanged = _CommentBlock_Info(false);

      }

  //}

  //[문서 출력]
  //{
      //[편집기] 내용 동기화.
      if(_select_ing == false)
      {
        //[2007.02.10.토]
        //[선택영역] 이 생성중인 경우는 여기서 아래 함수를 처리하지 않는다.
        _EditBuf_Text();

      }
  //}

  //[입력지정자]
  //{
      //현재 [줄이동] 중이므로 [선택영역] 이 해제 되지 않게 만든다.
      _scroll_ing = true;
      //{
          //[문서원점] 이 수정되었으므로 [입력지정자] 위치도 다시 설정한다.
          _EDIT_CaretPos(_caret_x, _caret_y);
      //}
      _scroll_ing = false;
  //}

  return;

}

void __fastcall Teditor_edit_Form::_EDIT_H_Scroll(void)
{
  //[2006.12.31.일][생성!!!]{---------------------------------------------
  //이 문서가 [수평 스크롤] 되는 경우 처리를 수행한다.
  //
  //[2007.02.11.일][수정!!!]
  //[줄이동] 중인 경우는 _scroll_ing == true 로 설정하여 _EDIT_CaretPos()
  //함수안에서 [선택영역] 이 해제되는 것을 막아야 한다.
  //
  //[2012.04.15.일][수정!!!]----------------------------------------------
  //}---------------------------------------------------------------------

  //[선언정보판 감추기]
  //{
      //[2012.04.15.일][추가!!!]
      if(info_tree_Form != NULL)
      {
        if(info_tree_Form->Visible == true) { info_tree_Form->Visible = false; }

      }

  //}

  //[문서 출력 원점 얻기]
  //{
      //[문서] 를 출력할 기준 원점을 구한다.
      //이미 [스크롤] 된 상태이므로 이 시점에서 [문서원점] 을 구해야 한다.
      _EDIT_Get_TextOrigin();
  //}

  //[문서 출력]
  //{
      //[편집기] 내용 동기화.
      _EditBuf_Text();
  //}

  //[입력지정자]
  //{
      //현재 [줄이동] 중이므로 [선택영역] 이 해제 되지 않게 만든다.
      _scroll_ing = true;
      //{
          //[문서원점] 이 수정되었으므로 [입력지정자] 위치도 다시 설정한다.
          _EDIT_CaretPos(_caret_x, _caret_y);
      //}
      _scroll_ing = false;
  //}

  return;

}

void __fastcall Teditor_edit_Form::_CARETINDEX_CaretIndexWidth(int   pLINEstartINDEX,
                                                               int   pCARETINDEX,
                                                               int  *rCARETINDEXwidth,
                                                               int  *rMOONJAcount)
{
  //[2006.12.27.수][생성!!!]{-----------------------------------------------
  //현재 _caretindex 가 위치한 행의 시작 부분에서 _caretindex 이전 문자의
  //모든 [폭] 을 더하여 실제 표시되는 [편집기] 상에서 _caretindex 가 위치한
  //문자까지의 [폭] 을 얻는다.
  //내부 처리시 자동으로 문자수까지 알게 되므로 [문자수] 도 같이 반환한다.
  //}-----------------------------------------------------------------------

  //[방법]
  //{
      //-----------------------------------------------------------------------
      //[영문] 을 제외 하고는 전부 [폭] 이 같으므로 [한글/영문] 의 [문자폭] 의
      //이미 구해 놓은 [대표값] 으로 간단하게 [폭] 을 구할수 있다.
      //즉, [영문] 인지 아닌지만 알면 각각의 문자 폭을 간단하게 알수 있다.
      //-----------------------------------------------------------------------
  //}

  //[주의!!!][2007.01.14.일]
  //{
      //-------------------------------------------------------------------------------------
      //한글은 첫 byte 만 [음수] 가 아니라 2byte 각각 모두 음수이다.
      //이점을 주의해야 한다.
      //단, '똠' 과 같은 문자가 입력되는 경우는 자동으로 OS 가 [조합형코드] 로
      //바꾸어서 전달하는데 이 [조함형코드] 는 무조건 첫 byte 가 [음수] 이다.
      //따라서 [한글/영문] 을 구분하기 위해서는 반드시 첫 byte 가 [음수] 인지 확인해야 한다.
      //이는 순서대로 처리할때는 문제가 없으나, 역방향으로 버퍼를 거꾸로 검사하는 경우는
      //반드시 첫 byte 가 [음수] 인지 확인해 보아야 한다.
      //-------------------------------------------------------------------------------------
  //}

  //[VAR]
  //{
      int  i            = 0;
      int  width        = 0;
      int  moonja_count = 0;

  //}

  for(i = pLINEstartINDEX; i < pCARETINDEX; i++)
  {
    //문자가 [한글/영문] 인지 구별하여 각각 문자의 [폭] 을 전부 합친다.
    if(_editbuf[i] > 0)
    {
      //이 경우는 [영문] 이다.
      width += _font_eng_width;

    }
    else
    {
      //[한글] 등 2 byte-code 문자의 경우.
      width += _font_kor_width;

      //2 byte-code 이므로 다음 위치로 이동해 놓는다.
      i++;

    }

    //문자수 증가.
    moonja_count++;

  }

  //[반환]
  //{
      //[2009.05.04.월][수정!!!]{-------
      //NULL 인 경우는 반환하지 않는다.
      //}-------------------------------

      if(rCARETINDEXwidth != NULL) { (*rCARETINDEXwidth) = width;        }
      if(rMOONJAcount     != NULL) { (*rMOONJAcount)     = moonja_count; }

  //}

  return;

}

void __fastcall Teditor_edit_Form::_CARETINDEXWIDTH_CaretIndex(int   pLINEstartINDEX,
                                                               int   pLINEendINDEX,
                                                               int  *prCARETINDEXwidth,
                                                               int  *rCARETINDEX,
                                                               int  *rMOONJAcount)
{
  //[2006.12.27.수][생성!!!]{-------------------------------------------------------------
  //_CARETINDEX_CaretIndexWidth() 함수와 정 반대로 형재 행의 _caretindexwidth 값으로
  //역으로 _caretindex 값을 구한다.
  //[한글/영문] 등이 섞여 있는 경우 항상 _caretindexwidth 에 정확하게 맞는 값을
  //얻을수 없으므로 가장 가까운 값을 구한다.(문자 위치에 정확하게 맞아야 한다.)
  //이는 행을 이동하는 경우등에 이전 행의 [입력지정자] 위치를 최대한 비슷하게 유지하기
  //위하여 사용될수 있다. 또한, 마우스로 찍은 경우 해당 위치에 [입력지정자] 를 위치시키는
  //데도 사용된다.
  //}-------------------------------------------------------------------------------------

  //[주의!!!]
  //{
      //처리할 행에 문자열이 없거나 이전 행보다 문자열이 작은 경우는
      //비슷한 [폭] 도 일치하는것이 없으므로 이 경우는 행의 가장 마지막 문자위치를 반환하면 된다.
      //추가로 수정된 cartindexwidth 값을 다시 반환한다.
  //}

  //[주의!!!][2007.01.14.일]
  //{
      //-------------------------------------------------------------------------------------
      //한글은 첫 byte 만 [음수] 가 아니라 2byte 각각 모두 음수이다.
      //이점을 주의해야 한다.
      //단, '똠' 과 같은 문자가 입력되는 경우는 자동으로 OS 가 [조합형코드] 로
      //바꾸어서 전달하는데 이 [조함형코드] 는 무조건 찻 byte 가 [음수] 이다.
      //따라서 [한글/영문] 을 구분하기 위해서는 반드시 첫 byte 가 [음수] 인지 확인해야 한다.
      //이는 순서대로 처리할때는 문제가 없으나, 역방향으로 버퍼를 거꾸로 검사하는 경우는
      //반드시 첫 byte 가 [음수] 인지 확인해 보아야 한다.
      //-------------------------------------------------------------------------------------
  //}

  //[VAR]
  //{
      int  i                = 0;
      int  caretindexwidth  = (*prCARETINDEXwidth);

      int  width_min        = 0;
      int  index_min        = pLINEstartINDEX;
      int  moonja_count_min = 0;

      int  width_max        = 0;
      int  index_max        = pLINEstartINDEX;
      int  moonja_count_max = 0;
  //}

  for(i = pLINEstartINDEX; i < pLINEendINDEX; )
  {
    //문자가 [한글/영문] 인지 구별하여 각각 문자의 [폭] 을 전부 합친다.

    if(_editbuf[i] > 0)
    {
      //이 경우는 [영문] 이다.
      width_max += _font_eng_width;

      i++;

    }
    else
    {
      //[한글] 등 2 byte-code 문자의 경우.
      width_max += _font_kor_width;

      //2 byte-code 이므로 다음 문자 위치로 이동해 놓는다.
      i += 2;

    }

    //문자수 증가.
    moonja_count_max++;

    //[폭비교]
    //{
        //전달받은 [폭] 에 근사한 경우는 이 값을 기록해 놓아야 한다.
        if(width_max >= caretindexwidth)
        {
          //원하는 값을 얻었으므로 더이상 처리하지 않고 종료한다.
          index_max = i;

          //[비교]
          //{
              //비교 대상이 되는 값과 보다 가까운 값을 찾는다.
              if((caretindexwidth - width_min) < (width_max - caretindexwidth))
              {
                //windth_min 이 현재 prCARETINDEXwidth 에 더 가깝다는 것이므로 이 값을 전달한다.

                (*prCARETINDEXwidth) = width_min;
                (*rCARETINDEX)       = index_min;
                (*rMOONJAcount)      = moonja_count_min;

                return;

              }
              else
              {
                //windth_max 이 현재 prCARETINDEXwidth 에 더 가깝다는 것이므로 이 값을 전달한다.

                (*prCARETINDEXwidth) = width_max;
                (*rCARETINDEX)       = index_max;
                (*rMOONJAcount)      = moonja_count_max;

                 return;

              }
          //}

        }
        else
        {
          //현재까지 구한 값을 저장해 놓는다.
          //이는 작은값 과 큰값중 어느 것이 더 가까운 값인지 구하기 위한 것이다.
          width_min        = width_max;
          index_min        = i;
          moonja_count_min = moonja_count_max;

        }
    //}
  }

  //[범위초과]
  //{
      //----------------------------------------------------------------------------
      //여기까지 온 경우는 이전 행의 [입력지정자] 위치가 지금 행의 총폭보다
      //큰 위치에 있는 경우이므로 무조건 지금행의 마지막 위치를 기록해 놓아야 한다.
      (*prCARETINDEXwidth) = width_max;
      (*rCARETINDEX)       = pLINEendINDEX;
      (*rMOONJAcount)      = moonja_count_max;
      //----------------------------------------------------------------------------
  //}

  return;

}

void __fastcall Teditor_edit_Form::_CARETINDEX_MoveLeft(int   pLINEstartINDEX,
                                                        int  *prCARETINDEX)
{
  //[2006.12.27.수][생성!!!]{------------------------------------------------------
  //_caretindex 를 왼쪽으로 수정하는 경우 [한글/영문] 인지 가려서 위치를 수정한다.
  //}------------------------------------------------------------------------------

  //[주의!!!][2007.01.14.일]
  //{
      //-------------------------------------------------------------------------------------
      //한글은 첫 byte 만 [음수] 가 아니라 2byte 각각 모두 음수이다.
      //이점을 주의해야 한다.
      //단, '똠' 과 같은 문자가 입력되는 경우는 자동으로 OS 가 [조합형코드] 로
      //바꾸어서 전달하는데 이 [조함형코드] 는 무조건 찻 byte 가 [음수] 이다.
      //따라서 [한글/영문] 을 구분하기 위해서는 반드시 첫 byte 가 [음수] 인지 확인해야 한다.
      //이는 순서대로 처리할때는 문제가 없으나, 역방향으로 버퍼를 거꾸로 검사하는 경우는
      //반드시 첫 byte 가 [음수] 인지 확인해 보아야 한다.
      //-------------------------------------------------------------------------------------
  //}

  //[수정!!!][2007.01.15.월]
  //{
      //---------------------------------------------------------------------------------
      //[한글 완성형] 은 2 byte 모두 [음수] 이나, [한글 조합형] 은 [음수:(음수/양수)] 로
      //첫 byte 는 반드시 [음수] 지만 두번째 byte 는 [음수/양수] 도 모두 될수 있어서
      //이전처럼 현 [입력지정자] 위치에서 거꾸로 검사하는 방식으로는 [입력지정자] 왼쪽의
      //문자가 [한글/영문] 인지 확실하게 구분할수 없다.
      //따라서, 이 행의 처음부터 현재 [입력지정자] 위치까지 검사해가는 방법을 사용해야
      //정확한 구분을 할수 있게 된다.
      //이렇게 수정한다.
      //---------------------------------------------------------------------------------
  //}

  //[VAR]
  //{
      bool  TkorFeng = false;
      int   i;
  //}

  //[확인]
  //{
      if((*prCARETINDEX) <= pLINEstartINDEX)
      {
        //현재 행 처음 위치보다 더이상 왼쪽으로 이동할수 없다.
        (*prCARETINDEX) = pLINEstartINDEX;
        return;
      }
  //}

  //[이 행 처음부터 추적한다]
  //{
      //이 행의 처음부터 현재 _caretindex 위치까지 순서대로 검사한다.
      //단, 다음 처리 전에 이미 이 행의 정확한 _linestartindex 값을 알고 있어야 한다.
      for(i = pLINEstartINDEX; i < _caretindex; )
      {
        if(_editbuf[i] < 0)
        {
          //[한글] 인 경우.
          i += 2;
          TkorFeng = true;

        }
        else
        {
          //[영문] 인 경우.
          i += 1;
          TkorFeng = false;

        }

      }

      //여기까지 현재 [입력지정자] 왼쪽 문자가 [한글/영문] 인지 이미 알아냈다.
  //}

  //[한글/영문 구분 처리]
  //{
      if(TkorFeng == true)
      {
        //지금 [입력지정자] 왼쪽의 문자는 [한글] 이다.
        (*prCARETINDEX) -= 2;

      }
      else
      {
        //지금 [입력지정자] 왼쪽의 문자는 [영문] 이다.
        (*prCARETINDEX) -= 1;

      }
  //}

  return;

}

void __fastcall Teditor_edit_Form::_CARETINDEX_MoveRight(int   pLINEendINDEX,
                                                         int  *prCARETINDEX)
{
  //[2006.12.27.수][생성!!!]{--------------------------------------------------------
  //_caretindex 를 오른쪽으로 수정하는 경우 [한글/영문] 인지 가려서 위치를 수정한다.
  //}--------------------------------------------------------------------------------

  //[주의!!!][2007.01.14.일]
  //{
      //-------------------------------------------------------------------------------------
      //한글은 첫 byte 만 [음수] 가 아니라 2byte 각각 모두 음수이다.
      //이점을 주의해야 한다.
      //단, '똠' 과 같은 문자가 입력되는 경우는 자동으로 OS 가 [조합형코드] 로
      //바꾸어서 전달하는데 이 [조함형코드] 는 무조건 찻 byte 가 [음수] 이다.
      //따라서 [한글/영문] 을 구분하기 위해서는 반드시 첫 byte 가 [음수] 인지 확인해야 한다.
      //이는 순서대로 처리할때는 문제가 없으나, 역방향으로 버퍼를 거꾸로 검사하는 경우는
      //반드시 첫 byte 가 [음수] 인지 확인해 보아야 한다.
      //-------------------------------------------------------------------------------------
  //}

  //[확인]
  //{
      if((*prCARETINDEX) >= pLINEendINDEX)
      {
        //현재 행 끝 위치보다 더이상 오른쪽으로 이동할수 없다.
        (*prCARETINDEX) = pLINEendINDEX;

        return;

      }
  //}

  //[문자] 로 판별한다.
  if(_editbuf[(*prCARETINDEX)] > 0)
  {
    //현재 위치 오른쪽 문자는 [영문] 이다.
    (*prCARETINDEX) += 1;

  }
  else
  {
    //현재 위치 오른쪽 문자는 [한글] 이다.
    (*prCARETINDEX) += 2;

  }

  return;

}

void __fastcall Teditor_edit_Form::_MOUSEDOWN_Get_LineStartIndex(int   pLINEnumber,
                                                                 int  *pLINEstartindex)
{
  //[2007.02.28.수][생성!!!]{------------------------------------------------------------
  //STR_Get_LineStartIndex() 함수를 대체하기 위한 함수로써,
  //결과를 _editbuf[] 처음부터 검사하여 얻지 않고 이미 구해진 _linetop_xxx 관련 변수를
  //참고하여 빠르게 구한다.
  //이는 양이 큰 문서의 경우(10만줄 3M) 마우스로 [선택영역] 을 형성할때
  //STR_Get_LineStartIndex() 함수로 인한 시간 손실을 막기 위한 것이다.

  //[2007.03.01.목][수정!!!]
  //_linetop_number 이후 (보이는 영역) 만 처리하지 않고 그 이전영역(보이지 않는 영역)도
  //같이 처리한다. 이는 [마우스] 를 사용하여 [선택영역] 을 형성하는 과정에서 보이지 않는
  //영역으로 들어 갈수 있기 때문이다.
  //이는 linestartindex 는 어떤 경우라도 항상 정확한 값을 추적하고 있어야 하기 때문이다.
  //}------------------------------------------------------------------------------------

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

  //[행 시작 위치 구하기]
  //{
      //현재 linetop 위치에서 지정 행까지의 행수를 구한다.(linetop 행은 제외)
      count = pLINEnumber - _linetop_linenumber;

      //검사를 시작할 index 위치를 기록한다.
      linestartindex = _linetop_startindex;

      if(count >= 0)
      {
        //가장 윗 행 다음의 행을 처리 하는 경우.(눈에 보이는 영역)

        //계속 지정 행 까지 현재 행의 startindex 값을 구한다.
        for(i = 0; i < count; i++)
        {
          //계속 다음행을 처리하는 것으로 값을 구한다.
          STR_Get_NextLineStartIndex(_editbuf, linestartindex, &linestartindex);

        }

      }
      else
      {
        //가장 윗 행 이전의 행을 처리 하는 경우.(눈에 안보이는 영역)

        //일단 양수로 바꿔준다.
        count = (-1) * count;

        for(i = 0; i < count; i++)
        {
          //계속 이전행을 처리하는 것으로 값을 구한다.
          STR_Get_BeforeLineStartIndex(_editbuf, linestartindex, &linestartindex);

        }

      }
  //}

  //[지정행 시작 위치 반환]
  //{
      (*pLINEstartindex) = linestartindex;
  //}

  return;

}

bool __fastcall Teditor_edit_Form::_CARETPOS_MouseDown(int  pMOUSEdownX,
                                                       int  pMOUSEdownY)
{
  //[2006.12.28.목][생성!!!]{--------------------------------------------------------------
  //[편집기] 상에 [마우스누르기] 하는 경우 이 위치에 자동으로 [입력지정자] 를
  //위치시켜준다.
  //이미 기록되 있는 각각의 정보를 사용하여 위치를 산출한다.
  //단, 현재 문서의 행을 넘은 영역을 찍은 경우는 마지막 행을 찍은 것으로 본다.
  //
  //[2007.02.08.목][수정!!!]---------------------------------------------------------------
  //행은 [음수] 가 될수 없으므로 [음수] 행이 나오는 경우는 0 으로 초기화 한다.
  //
  //[2007.02.26.월][추가!!!]---------------------------------------------------------------
  //새로 구한 위치가 이전 _caret_x, _caret_y 위치와 차이가 없는 경우는 false 를 반환하고,
  //수정된 경우는 true 를 반환한다.
  //
  //[2007.03.19.월][수정!!!]---------------------------------------------------------------
  //마우스로 [선택영역] 을 만드는 경우 [입력지정자] 의 위치가 보이지 않는 영역에 있게 되는
  //경우가 발생하지 않도록 수정하였다.
  //}--------------------------------------------------------------------------------------

  //[주의!!!]
  //{
      //-------------------------------------------------------------------
      //[행 수] 는 1부터 유효한 값이고, [행 번호] 는 0 부터 유효한 값이다.
      //-------------------------------------------------------------------
  //}

  //[VAR]
  //{
      int  mouse_x, mouse_y;
      int  linenum; //(BASE : 0)

      //[2007.02.26.월][추가!!!]
      int  caret_x, caret_y;

  //}

  //[영역 검사]
  //{
      //[2007.03.19.월]{---------------------------------------------------------
      //[입력지정자] 가 보이지 않는 영역에 있어서는 안되므로, 항상 보이는 영역에
      //위치하도록 값을 자동으로 수정해 준다.
      //}------------------------------------------------------------------------

      //[수직 검사]
      //{
          if     (pMOUSEdownY < _line_height)
          {
            //[위쪽]
            pMOUSEdownY = _line_height;

          }
          else if(pMOUSEdownY > (this->Height - editor_info_Form->Height - _line_height))
          {
            //[아래쪽]
            pMOUSEdownY = this->Height - editor_info_Form->Height - _line_height;

          }

      //}

      //[수평 검사]
      //{
          if     (pMOUSEdownX < 0)
          {
            //[왼쪽]
            pMOUSEdownX = 0;

          }
          else if(pMOUSEdownX > (this->Width - ide_editor_Form->_scroll_v_Form->Width))
          {
            //[오른쪽]
            pMOUSEdownX = (this->Width - ide_editor_Form->_scroll_v_Form->Width);

          }

      //}

  //}

  //[문서상 위치 환산]
  //{
      //[문서원점] 을 기준으로한 문서상의 위치를 구한다.
      mouse_x = (pMOUSEdownX - _text_org_x);
      mouse_y = (pMOUSEdownY - _text_org_y);

  //}

  //[행관련 정보 구하기]
  //{
      //현재 [행 번호] 를 구한다.
      linenum = mouse_y / _line_height;

      //[행 범위 확인]
      //{
          if     (!(linenum < _linecount))
          {
            //지정행은 [문서총행] 을 넘을수 없다.
            //행번호는 0 부터다.
            linenum = (_linecount - 1);

          }
          else if(linenum < 0)
          {
            //[2007.02.08.목][추가!!!]
            //지정행은 0 행보다 작을수 없다.(즉, [음수] 행은 존재하지 않는다.)
            linenum = 0;

          }

      //}

      //현재 행의 시작위치를 구한다.
      _MOUSEDOWN_Get_LineStartIndex(linenum, &_linestartindex);
      //STR_Get_LineStartIndex(_editbuf, linenum, &_linestartindex); //이전사용함수.
      //[참고][2007.03.01.목]
      //{
          //STR_Get_LineStartIndex() 함수는 문서 전체를 처음부터 추적하여 행을 구하므로
          //문서 량이 10만줄 정도 되면 처리 시간이 길어 질수 있다.
          //그러나, 10만줄(3M 용량)의 경우라도 <Release-Mode> 로 빌드한 경우는
          //마우스로 [선택영역] 을 형성해 가는 경우도 처리 속도의 저하를 느낄수 없었다.
          //그러나, 더 빠르게 처리되는 _MOUSEDOWN_Get_LineStartIndex() 함수로 대체한다.
      //}

      //현재 행의 끝 위치를 구한다.
      STR_Get_ThisLineEndIndex(_editbuf, _linestartindex, &_lineendindex);

  //}

  //[_caretindex 구하기]
  //{
      //일단 mouse_x 위치를 _caretindexwidth 로 보고 _caretindex 값을 구한다.
      _caretindexwidth = mouse_x;

      //중요 정보를 얻는다.
      _CARETINDEXWIDTH_CaretIndex(_linestartindex, _lineendindex,
                                  &_caretindexwidth, &_caretindex, &_col);

  //}

  //[입력지정자 위치 설정]
  //{
      //[문서] 상의 위치를 구한다.
      caret_x = _caretindexwidth;
      caret_y = linenum * _line_height;

      if((caret_x == _caret_x) && (caret_y == _caret_y))
      {
        //[2007.02.26.월][추가!!!]{---------------------
        //위치가 그대로 인경우이므로 false 를 반환한다.
        //}---------------------------------------------

        return(false);

      }

      _caret_x = caret_x;
      _caret_y = caret_y;

      //위치시킨다.
      _EDIT_CaretPos(_caret_x, _caret_y);

  //}

  return(true);

}

void __fastcall Teditor_edit_Form::_ROOT_TEXTINFO_Init(void)
{
  //[2007.01.04.목][생성!!!]{----------------------------------------------
  //실제 사용되는 문서 정보를 초기화 한다.
  //이는 [문서] 를 처음 여는 경우 표시 위치등을 완전히 초기화 하는 것이다.
  //
  //[2012.06.09.토][추가!!!]-----------------------------------------------
  //}----------------------------------------------------------------------

  _font.margin_size = d_gutter_width + 2 - 1;

  _text_org_x = _font.margin_size;
  _text_org_y = 2;

  //행은 기본적으로 무조건 한개는 있는 것으로 해야 [줄이동막대] 가 제대로 동작한다.
  _linecount = 1;

  _linestartindex = 0;
  _lineendindex   = 0;

  _linetop_startindex = 0;
  _linetop_linenumber = 0;

  _caretindex      = 0;
  _caretindexwidth = 0;

  //[단어 구간 정보]
  //{
      //[2012.05.24.목][추가!!!]
      _wordStartIndex = 0;
      _wordEndIndex   = 0;

  //}

  //[세로줄]
  //{
      //[2012.06.09.토][추가!!!]
      _vLineEn = false;
      _vLineX  = -1;
      //처음에는 항상 <true> 로 함수동작 상태로 설정.
      _sw_VLine = true;

  //}

  //[주석정보 초기화]
  //{
      //[2012.06.09.토][추가!!!]{-----------------------
      //첫 항목만 초기화 한다.
      //한번도 사용하지 않았다는 의미로 <-1> 로 초기화.
      //}-----------------------------------------------
      
      _cmtBlockInfo.itemCount = -1;

  //}

  _row = 0;
  _col = 0;

  _caret_x = 0;
  _caret_y = 0;

  _editbuf_text_on = true;

  //[2007.04.05.목][추가!!!]
  //처음 문서는 수정되지 않은 상태이다.
  //_changed = false;
  _EDIT_Changed(true, false);

  //[2009.03.31.화][추가!!!]
  //읽기전용 속성 초기화(기본은 수정 가능한 상태).
  _readOnly = false;

  //[2009.03.31.화][추가!!!]
  //기본적으로 [색동문자] 가 적용되지 않는 일반 문서로 설정한다.
  _fileKind = d_Editor_FileKind_default;

  //[문서 용도 종류]
  //{
      //[2022.06.27.월][추가]
      _fileUseKind = d_Editor_fileUseKind_Default;

  //}

  //[문서 수정 이력 초기화]{---
  //[2009.05.03.일]
  History_Init();
  //}--------------------------

  //[검증식 보기판]
  //{
      //[2011.07.01.금][추가!!!]{----------------------------------------------
      //이 함수는 <_EDITFILE_Open()> 함수에서 [아직 열려있지 않은 문서열기] 시
      //호출되어 현재 [편집기] 의 [문서정보] 를 초기화 하게 된다.
      //따라서, 반드시 [검증식 보기판] 의 정보도 같이 설정해 주어야 한다.
      //
      //[주의!!!]--------------------------------------------------------------
      //바로 아래서 <_Select_CaretIndex()> 에서 조건에 따라 [검증식 보기판] 이
      //다시 그려질수 있으므로 반드시 여기서 먼저 처리해 주어야 한다.
      //}----------------------------------------------------------------------

      _dbgView_Visible          = false;
      _dbgView_State            = '+';
      //기본은 16진수 보기이다.
      //[2011.07.21.목][수정!!!]
      //[정의이름] 으로 변경한다.
      _dbgViewDspInfo.viewKind  = Opt_Ide_DbgExpView_Mode;

  //}

  //[선택영역]
  //{
      //[2007.03.17.토][추가!!!]
      //[선택영역] 을 초기화 한다.
      //둘중 하나라도 -1 인 경우는 [선택영역] 이 존재하지 않는것이다.
      _Select_CaretIndex(&_select_start, -1); //_select_start.caret_index = -1;
      _select_start.caret_x     = 0;
      _select_start.caret_y     = 0;

      _Select_CaretIndex(&_select_end, -1); //_select_end.caret_index   = -1;
      _select_end.caret_x       = 0;
      _select_end.caret_y       = 0;

  //}

  //[정지점 초기화]
  //{
      //[2007.04.13.금][추가!!!]
      _BREAKPOINT_Init(&_breakpoint);

  //}

  return;

}

void __fastcall Teditor_edit_Form::_TEXTINFO_Format(struct TEXTINFO  *pTEXTINFO)
{
  //[2007.01.02.화][생성!!!]{-------------
  //한개의 항목을 초기화 한다.
  //
  //[2011.06.26.일][추가!!!]--------------
  //[검증식 보기판] 관련 항목을 추가한다.
  //
  //[2012.06.09.토][추가!!!]--------------
  //}-------------------------------------

  pTEXTINFO->filename = "";

  pTEXTINFO->filesize = 0;

  pTEXTINFO->font_margin_size = d_gutter_width + 2 - 1;

  pTEXTINFO->text_org_x = 0;
  pTEXTINFO->text_org_y = 0;

  pTEXTINFO->linecount = 0;

  pTEXTINFO->linestartindex = 0;
  pTEXTINFO->lineendindex   = 0;

  pTEXTINFO->linetop_startindex = 0;
  pTEXTINFO->linetop_linenumber = 0;

  pTEXTINFO->caretindex      = 0;
  pTEXTINFO->caretindexwidth = 0;

  //[단어 구간 정보]
  //{
      //[2012.05.24.목][추가!!!]
      pTEXTINFO->wordStartIndex = 0;
      pTEXTINFO->wordEndIndex   = 0;

  //}

  //[세로줄]
  //{
      //[2012.06.09.토][추가!!!]
      pTEXTINFO->vLineEn = false;
      pTEXTINFO->vLineX  = -1;

  //}

  pTEXTINFO->row = 0;
  pTEXTINFO->col = 0;

  pTEXTINFO->caret_x = 0;
  pTEXTINFO->caret_y = 0;

  //[2007.04.07.토][추가!!!]
  pTEXTINFO->changed = false;

  //[2009.04.01.수][추가!!!]
  pTEXTINFO->readOnly = false;

  pTEXTINFO->fileKind = d_Editor_FileKind_default;

  //[정지점]
  //{
      //[2007.04.13.금][추가!!!]
      //[정지점] 을 초기화 한다.
      _BREAKPOINT_Init(&(pTEXTINFO->breakpoint));
  //}

  //[선택영역정보][2007.01.22.월]
  //{
      pTEXTINFO->select_start.caret_index = -1;
      pTEXTINFO->select_start.caret_x     = 0;
      pTEXTINFO->select_start.caret_y     = 0;

      pTEXTINFO->select_end.caret_index   = -1;
      pTEXTINFO->select_end.caret_x       = 0;
      pTEXTINFO->select_end.caret_y       = 0;
  //}

  pTEXTINFO->scroll_V_min         = 0;
  pTEXTINFO->scroll_V_max         = 0;
  pTEXTINFO->scroll_V_position    = 0;
  pTEXTINFO->scroll_V_design_size = 0;

  pTEXTINFO->scroll_H_min         = 0;
  pTEXTINFO->scroll_H_max         = 0;
  pTEXTINFO->scroll_H_position    = 0;
  pTEXTINFO->scroll_H_design_size = 0;

  //[검증식 보기판]
  //{
      //[2011.06.26.일][추가!!!]
      pTEXTINFO->dbgView_Visible  = false;
      pTEXTINFO->dbgView_State    = '+';
      //[2011.07.01.금][추가!!!]
      //처음에는 [16진수] 보기가 기본이다.
      //[2011.07.21.목][수정!!!]
      //[정의이름] 으로 변경한다.
      pTEXTINFO->dbgView_ViewKind = Opt_Ide_DbgExpView_Mode;

  //}

  //[문서 용도 종류]
  //{
      //[2022.06.27.월][추가]
      pTEXTINFO->fileUseKind = d_Editor_fileUseKind_Default;

  //}

}

void __fastcall Teditor_edit_Form::_TEXTINFO_Init(void)
{
  //[2007.01.02.화][생성!!!]{-------
  //_textinfo[] 전체를 초기화 한다.
  //}-------------------------------

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

  for(i = 0; i < d_TEXTINFO_max; i++)
  {
    _TEXTINFO_Format(&(_textinfo[i]));

  }

  return;

}

void __fastcall Teditor_edit_Form::_TEXTINFO_Add(struct TEXTINFO  *pTEXTINFO)
{
  //[2007.01.01.월][생성!!!]{----------------------
  //현재 저장된 가장 뒷 부분에 새 정보를 추가한다.
  //}----------------------------------------------

  //마지막 위치에 할당한다.
  _textinfo[_textinfo_count] = (*pTEXTINFO);

  _textinfo_count++;

  return;

}

void __fastcall Teditor_edit_Form::_TEXTINFO_Delete(int  pDELETEindex)
{
  //[2007.01.01.월][생성!!!]{------
  //지정 index 의 항목을 삭제한다.
  //}------------------------------

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

  for(i = pDELETEindex; i < _textinfo_count; i++)
  {
    //현재 위치로 다음것을 당겨 붙인다.
    _textinfo[i] = _textinfo[i + 1];

  }

  //항목이 한개 삭제 되었으므로 항목수를 하나 감소시킨다.
  _textinfo_count--;

  return;

}

int __fastcall Teditor_edit_Form::_TEXTINFO_GetIndex_withFILEname(AnsiString  pFILEname)
{
  //[2007.03.30.금][생성!!!]{---------------------------
  //pFILEname 에 해당하는 목록의 index 를 반환한다.
  //pFILEname 은 경로까지 전부 포함된 이름이다.
  //해당하는 것이 없는 경우는 -1 을 반환한다.
  //
  //[2009.05.21.목][중요수정!!!]------------------------
  //[문서이름] 은 절대 [대/소 문자] 를 구분하면 안된다.
  //}---------------------------------------------------

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

  //[대상문서 찾기]
  //{
      //pFILEname 과 같은 이름의 문서를 목록에서 찾는다.
      for(i = 0; i < _textinfo_count; i++)
      {
        //[2009.05.21.목][중요수정!!!]{--------------------------------------------------
        //문서 이름의 [대/소 문자] 를 구분을 하지 않기 위하여 직접 만든 함수를 사용한다.
        //}------------------------------------------------------------------------------

        if(STR_Match_NoCase(pFILEname.c_str(), _textinfo[i].filename.c_str()) == true)
        {
          return(i);

        }

      }
  //}

  //여기까지 온것은 찾는 것이 없는 것이다.
  return(-1);

}

int __fastcall Teditor_edit_Form::_TEXTINFO_GetIndex_withFileUseKind(int  pFileUseKind)
{
  //[2022.06.27.월][생성]{-----------------------------
  //<pFileUseKind> 에 해당하는 목록의 <index> 를 반환.
  //해당하는 것이 없는 경우는 <-1> 을 반환.
  //}--------------------------------------------------

  //[VAR]
  //{
      int  i;

  //}

  //[대상문서 찾기]
  //{
      //pFileUseKind 과 같은 이름의 문서를 목록에서 찾기.
      for(i = 0; i < _textinfo_count; i++)
      {
        if(pFileUseKind == _textinfo[i].fileUseKind)
        {
          return(i);

        }

      }

  //}

  //여기까지 온것은 찾는 것이 없는 것이다.
  return(-1);

}

//v---<TEXTINFO[]> 에서 기록한 대상 문서 항목 번호(해당 항목이 없는 경우는 <-1>).
int __fastcall Teditor_edit_Form::_TEXTINFO_Set_FileUseKind(//<TEXTINFO[]> 에서 기록 대상 문서 [전체경로이름확장자].
                                                            char  *pFilePathNameExt,
                                                            //기록할 문서 용도.
                                                            int    pFileUseKind)
{
  //[2022.06.27.월][생성]{--------------------------------------------------------------
  //<pFilePathNameExt> 에 해당하는 <TEXTINFO[].fileUseKind> 에 <pFileUseKind> 를 기록후
  //해당 [항목번호] 를 반환(해당하는 것이 없는 경우는 <-1> 을 반환).
  //}-----------------------------------------------------------------------------------

  //[VAR]
  //{
      int  itemIndex;

  //}

  //[항목 번호 찾기]
  //{
      itemIndex = _TEXTINFO_GetIndex_withFILEname((AnsiString)pFilePathNameExt);

      //해당 항목이 없다면 <-1> 을 반환하고 즉시 종료.
      if(itemIndex == -1) return(-1);

  //}

  //[정보 기록]
  //{
      _textinfo[itemIndex].fileUseKind = pFileUseKind;

  //}

  //해당 [항목번호] 반환.
  return(itemIndex);

}

void __fastcall Teditor_edit_Form::_TEXTINFO_Backup(int  pINDEX)
{
  //[2007.01.02.화][생성!!!]{----------------------------------------------------
  //현재 문서의 독립 정보들을 지정 위치에 저장한다.
  //현재 정보를 저장하는 것은 복구하는 것에 비하여 다른 것에 영향을 주지 않는다.
  //
  //[2009.05.05.화][추가!!!]-----------------------------------------------------
  //현재 문서의 <수정이력> 을 <*.urd> 문서로 같은 위치에 저장해 준다.
  //
  //[2011.06.26.일][추가!!!]-----------------------------------------------------
  //[검증식 보기판] 관련 항목을 추가한다.
  //
  //[2012.06.09.토][추가!!!]-----------------------------------------------------
  //}----------------------------------------------------------------------------

  if(pINDEX < 0) return;

  //이것은 이미 _textinfo[] 상의 정보를 직접 사용하므로 상관없이 그대로 사용하면된다.
  //_textinfo[pINDEX].filename 는 그대로 둔다.

  //현재 문서크기를 저장한다.
  _textinfo[pINDEX].filesize = _filesize;

  //수평 스크롤 정보를 위하여 필요하다.
  _textinfo[pINDEX].font_margin_size = _font.margin_size;

  _textinfo[pINDEX].text_org_x = _text_org_x;
  _textinfo[pINDEX].text_org_y = _text_org_y;

  _textinfo[pINDEX].linecount          = _linecount;
  _textinfo[pINDEX].linestartindex     = _linestartindex;
  _textinfo[pINDEX].lineendindex       = _lineendindex;
  _textinfo[pINDEX].linetop_startindex = _linetop_startindex;
  _textinfo[pINDEX].linetop_linenumber = _linetop_linenumber;

  _textinfo[pINDEX].caretindex      = _caretindex;
  _textinfo[pINDEX].caretindexwidth = _caretindexwidth;

  //[단어 구간 정보]
  //{
      //[2012.05.24.목][추가!!!]
      _textinfo[pINDEX].wordStartIndex = _wordStartIndex;
      _textinfo[pINDEX].wordEndIndex   = _wordEndIndex;

  //}

  //[세로줄]
  //{
      //[2012.06.09.토][추가!!!]
      _textinfo[pINDEX].vLineEn = _vLineEn;
      _textinfo[pINDEX].vLineX  = _vLineX;

  //}

  _textinfo[pINDEX].row = _row;
  _textinfo[pINDEX].col = _col;

  _textinfo[pINDEX].caret_x = _caret_x;
  _textinfo[pINDEX].caret_y = _caret_y;

  //[2007.04.05.목][추가!!!]
  _textinfo[pINDEX].changed = _changed;

  //[2009.03.31.화][추가!!!]
  _textinfo[pINDEX].readOnly = _readOnly;

  //[2009.03.31.화][추가!!!]
  _textinfo[pINDEX].fileKind = _fileKind;

  //[문서 용도 종류]
  //{
      //[2022.06.27.월][추가]
      _textinfo[pINDEX].fileUseKind = _fileUseKind;

  //}

  //[정지점]
  //{
      //[2007.04.13.금][추가!!!]
      _textinfo[pINDEX].breakpoint = _breakpoint;
  //}

  //[선택영역정보][2007.01.22.월]
  //{
      _textinfo[pINDEX].select_start = _select_start;
      _textinfo[pINDEX].select_end   = _select_end;
  //}

  //[스크롤 정보]
  //{
      _textinfo[pINDEX].scroll_V_min         = ide_editor_Form->_scroll_v_Form->_min;
      _textinfo[pINDEX].scroll_V_max         = ide_editor_Form->_scroll_v_Form->_max;
      _textinfo[pINDEX].scroll_V_position    = ide_editor_Form->_scroll_v_Form->_position;
      _textinfo[pINDEX].scroll_V_design_size = ide_editor_Form->_scroll_v_Form->_design_size;

      _textinfo[pINDEX].scroll_H_min         = ide_editor_Form->_scroll_h_Form->_min;
      _textinfo[pINDEX].scroll_H_max         = ide_editor_Form->_scroll_h_Form->_max;
      _textinfo[pINDEX].scroll_H_position    = ide_editor_Form->_scroll_h_Form->_position;
      _textinfo[pINDEX].scroll_H_design_size = ide_editor_Form->_scroll_h_Form->_design_size;

  //}

  //[<수정이력> 저장]
  //{
      //[2009.05.05.화][추가!!!]{----------------------------------------
      //현재 문서의 [수정이력] 을 [수정이력] 문서인 <*.urd> 에 저장한다.
      //}----------------------------------------------------------------

      History_FileSave(_textinfo[pINDEX].filename.c_str());

  //}

  //[검증식 보기판]
  //{
      //[2011.06.26.일][추가!!!]
      _textinfo[pINDEX].dbgView_Visible  = _dbgView_Visible;
      _textinfo[pINDEX].dbgView_State    = _dbgView_State;

      //[2011.07.01.금][추가!!!]
      _textinfo[pINDEX].dbgView_ViewKind = _dbgViewDspInfo.viewKind;

  //}

  //[문서 용도 종류]
  //{
      //[2022.06.27.월][추가]
      _textinfo[pINDEX].fileUseKind = _fileUseKind;

  //}

  return;

}

void __fastcall Teditor_edit_Form::_TEXTINFO_Restore(int  pINDEX)
{
  //[2007.01.02.화][생성!!!]{-----------------------------------------------------
  //지정 위치의 문서 정보를 현재 문서 정보로 복구시킨다.
  //복구할때는 상태에 영향을 주어야 하므로 [스크롤] 설정의 경우는
  //지정 함수를 사용하여 설정값이 다시 반영될수 있도록 해야 한다.
  //
  //[2009.05.05.화][추가!!!]------------------------------------------------------
  //현재 문서의 <수정이력> 문서인 <*.urd> 문서를 읽어서 <수정이력> 을 복구해준다.
  //
  //[2011.06.26.일][추가!!!]------------------------------------------------------
  //[검증식 보기판] 관련 항목을 추가한다.
  //
  //[2012.06.09.토][추가!!!]------------------------------------------------------
  //}-----------------------------------------------------------------------------

  if(pINDEX < 0) return;

  //이것은 이미 _textinfo[] 상의 정보를 직접 사용하므로 상관없이 그대로 사용하면된다.
  //_textinfo[pINDEX].filename 는 그대로 둔다.

  //문서크기를 복구한다.
  _filesize = _textinfo[pINDEX].filesize;

  //수평 스크롤 정보를 위하여 필요하다.
  _font.margin_size = _textinfo[pINDEX].font_margin_size;

  //[문서원점] 복구.
  _text_org_x = _textinfo[pINDEX].text_org_x;
  _text_org_y = _textinfo[pINDEX].text_org_y;

  _linecount          = _textinfo[pINDEX].linecount;
  _linestartindex     = _textinfo[pINDEX].linestartindex;
  _lineendindex       = _textinfo[pINDEX].lineendindex;
  _linetop_startindex = _textinfo[pINDEX].linetop_startindex;
  _linetop_linenumber = _textinfo[pINDEX].linetop_linenumber;

  _caretindex      = _textinfo[pINDEX].caretindex;
  _caretindexwidth = _textinfo[pINDEX].caretindexwidth;

  //[단어 구간 정보]
  //{
      //[2012.05.24.목][추가!!!]
      _wordStartIndex = _textinfo[pINDEX].wordStartIndex;
      _wordEndIndex   = _textinfo[pINDEX].wordEndIndex;

  //}

  //[세로줄]
  //{
      //[2012.06.09.토][추가!!!]
      _vLineEn = _textinfo[pINDEX].vLineEn;
      _vLineX  = _textinfo[pINDEX].vLineX;

  //}

  //[입력 지정자 복구]
  //{
      //[행/열] 복구.
      _row = _textinfo[pINDEX].row;
      _col = _textinfo[pINDEX].col;

      //[입력지정자] 위치 복구.
      _caret_x = _textinfo[pINDEX].caret_x;
      _caret_y = _textinfo[pINDEX].caret_y;


      //[2011.07.02.토][중요추가!!!]{---------------------------------------------------------------------------
      //[문서전환] 시 아래 <_EDIT_CaretPos()> 함수안에서 <_EditBuf_Text()> 함수를
      //호출하게 되는데, 이 시점에서는 아직 [검증식 보기판] 이 [재설정] 되지 않은
      //상태라 [검증식 보기판] 이 이 문서에 보여지고 있는 경우는
      //1) [검증식 보기판] 없이 [편집기] 가 한번 그려진 후
      //2) 아래의 [검증식 보기판] 이 재설정된 후 다시 한번 < ide_editor_Form->_scroll_h_Form->_Position()> 에서
      //   [편집기] 가 다시 그려질때 [검증식 보기판] 이 그려지게 되어
      //결과적으로 [깜박이는] 문제가 발생한다.
      //매우 보기 좋지 않고, [편집기] 가 두번 그려지게 되므로 여기서는 [편집기] 가 그려지지 않도록 한다.
      _editbuf_text_on = false;
      //{
          //[행/열] 정보도 해당 위치에 표시해 주어야 하므로 함수를 사용하여 다시 위치를 설정한다.
          _EDIT_CaretPos(_caret_x, _caret_y);

      //}
      _editbuf_text_on = true;
      //}-------------------------------------------------------------------------------------------------------
      
  //}

  //[2007.04.05.목][추가!!!]
  //_changed = _textinfo[pINDEX].changed;
  _EDIT_Changed(true, _textinfo[pINDEX].changed);

  //[2009.03.31.화][추가!!!]
  _readOnly = _textinfo[pINDEX].readOnly;

  //[2009.03.31.화][추가!!!]
  _fileKind = _textinfo[pINDEX].fileKind;

  //[문서 용도 종류]
  //{
      //[2022.06.27.월][추가]
      _fileUseKind = _textinfo[pINDEX].fileUseKind;

  //}

  //[정지점]
  //{
      //[2007.04.13.금][추가!!!]
      _breakpoint = _textinfo[pINDEX].breakpoint;

  //}

  //[검증식 보기판]
  //{
      //[2011.07.02.토][중요수정!!!]{----------------------------------------------
      //아래의 <ide_editor_Form->_scroll_x_Form->_Position()> 함수 부분에서
      //자동적으로 [편집기] 가 그려지므로 여기서는 [선택영역 복구] 이전에
      //[검증식 보기판] 을 재설정해도 무관한다.
      //[문서전환] 시에는 반드시 <ide_editor_Form->_scroll_x_Form->_Position> 에서
      //[편집기] 가 다시 그려지므로 그 이전에 처리하면 된다.
      //}--------------------------------------------------------------------------

      //[2011.06.26.일][추가!!!]
      _dbgView_Visible         = _textinfo[pINDEX].dbgView_Visible;
      _dbgView_State           = _textinfo[pINDEX].dbgView_State;

      //[2011.07.01.금][추가!!!]
      _dbgViewDspInfo.viewKind = _textinfo[pINDEX].dbgView_ViewKind;

      //[주의!!!]{--------------------------------------------------------------------
      //[검증식 보기판] 이 보여지는 설정인 경우는 이전 [문서] 의 내용이 보이지 않도록
      //반드시 다시 그려주어야 한다.
      //}-----------------------------------------------------------------------------
      
      if(_dbgView_Visible == true)
      {
        _DbgView_Shape();

      }

  //}

  //[선택영역정보][2007.01.22.월]
  //{
      _select_start = _textinfo[pINDEX].select_start;
      _select_end   = _textinfo[pINDEX].select_end;

  //}

  //[스크롤 정보]
  //{
      //스크롤 정보는 가장 먼저 설정되어야 한다.

      //[수평 스크롤]{--------------------------------------------------------------------------------------------
      //지금 [스크롤] 시의 문서 출력은 하지 못하게 한다.(중복방지)
      _editbuf_text_on = false;
      //{
          ide_editor_Form->_scroll_h_Form->_design_size = _textinfo[pINDEX].scroll_H_design_size;
          ide_editor_Form->_scroll_h_Form->_min = _textinfo[pINDEX].scroll_H_min;
          ide_editor_Form->_scroll_h_Form->_max = _textinfo[pINDEX].scroll_H_max;
          //실제 적인 모든 것은 _Position() 에서 처리 되므로 다른 것은 직접 값을 주고 함수는 _Position() 만 호출한다.
          ide_editor_Form->_scroll_h_Form->_Position(_textinfo[pINDEX].scroll_H_position);
      //}
      //다시 출력 허용.
      _editbuf_text_on = true;
      //[수직 스크롤]{--------------------------------------------------------------------------------------------
      ide_editor_Form->_scroll_v_Form->_design_size = _textinfo[pINDEX].scroll_V_design_size;
      ide_editor_Form->_scroll_v_Form->_min = _textinfo[pINDEX].scroll_V_min;
      ide_editor_Form->_scroll_v_Form->_max = _textinfo[pINDEX].scroll_V_max;
      //실제 적인 모든 것은 _Position() 에서 처리 되므로 다른 것은 직접 값을 주고 함수는 _Position() 만 호출한다.
      ide_editor_Form->_scroll_v_Form->_Position(_textinfo[pINDEX].scroll_V_position);
      //}---------------------------------------------------------------------------------------------------------
  //}

  //[스크롤 다시 설정][주의!!!]
  //{
      //---------------------------------------------------------------------------
      //이 함수를 호출하는 _EDITFILE_ReOpen() 함수 안에서 자동으로 다시 설정되므로
      //여기서는 [깜박임] 발생을 줄이기 위하여 처리하지 않는다.
      //---------------------------------------------------------------------------
  //}

  //[<수정이력> 복구]
  //{
      //[2009.05.05.화][추가!!!]{-------------------------------------
      //현재 문서의 [수정이력] 문서인 <*.urd> 을 읽어들여 복구해준다.
      //}-------------------------------------------------------------

      History_FileOpen(_textinfo[pINDEX].filename.c_str());

  //}

  return;

}

bool __fastcall Teditor_edit_Form::_TEXTINFO_IsChangedOne(void)
{
  //[2007.04.10.화][생성!!!]{----------------------------------------------------
  //현재 [문서목록] 의 문서중 한개라도 수정된 것이 있는 경우는 true 를 반환한다.
  //}----------------------------------------------------------------------------

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

  for(i = 0; i < _textinfo_count; i++)
  {
    if(i == _textinfo_index)
    {
      //현재 편집중인 문서인 경우.

      //변경된 문서가 발견되는 즉시 바로 true 를 반환하고 종료한다.
      if(_changed == true) return(true);

    }
    else
    {
      //목록에 있는 다른 문서의 경우.

      //변경된 문서가 발견되는 즉시 바로 true 를 반환하고 종료한다.
      if(_textinfo[i].changed == true) return(true);

    }

  }

  //여기까지 온것은 수정된 문서가 하나도 없는 경우이다.
  return(false);

}

void __fastcall Teditor_edit_Form::_KEY_Up(bool  pETCcontrol)
{
  //[2007.01.07.일][생성!!!]{---------------------------------------------------------------------
  //[방향키-위] 로 [입력지정자] 를 이동중 [편집기] 윗 부분을 벗어나는 경우는
  //항상 [입력지정자] 가 가장 윗행에 위치할수 있도록 자동으로 1행 윗줄로 [스크롤] 해 주어야 한다.

  //[2007.02.09.금][추가!!!]
  //[키] 를 사용하여 [선택영역] 을 만드는 경우의 처리를 추가한다.

  //[2007.03.13.화][추가!!!]
  //순수하게 [입력지정자] 를 이동하는 경우는 먼저 _CARET_ViewAlways() 함수를 별도로 먼저
  //실행하게 되는데, 이 때 이 함수의 실행 결과에 따라서 _EditBuf_Text() 함수가 중복 처리되지
  //않도록 해 주어야 한다.
  //pETCcontrol 이 true 인 경우는 _EditBuf_Text() 를 처리하지 않게 만든다.
  //}---------------------------------------------------------------------------------------------

  //[VAR]
  //{
      //현재 position 값.
      int  position       = ide_editor_Form->_scroll_v_Form->_position;

      //현재 값.
      int  position_save  = position;

      //실제 변화된 행수.
      int  real_count     = 0;

      //미리 [입력지정자] 의 위치를 비교를 위하여 산출한다.
      int  caret_next_pos = (_caret_y - _line_height);

      //변화하기 전의 현재 _caretindex 값을 저장해 놓는다.
      int  caretindex     = _caretindex;
      int  caret_x        = _caret_x;
      int  caret_y        = _caret_y;
  //}

  //[스크롤해야 하나?]
  //{
      //[입력지정자] 가 보이는 영역을 벗어 난 경우라면 윗줄로 스크롤한다.
      if(_linetop_linenumber > ( caret_next_pos / _line_height))
      {
        //[주의!!!]{--------------------------------------------------------------------------
        //여기서 [스크롤] 되는 경우는 _EDIT_V_Scroll() 함수 안에서 _EDIT_CaretPos() 함수가
        //처리 되어서는 안된다. 이렇게 하지 않으면 [입력지정자] 가 계속 위아래로 이동하는것이
        //보이므로 보기 좋지 않게 된다. (이 함수 마지막에 한번만 처리 되도록 한다.)
        //}-----------------------------------------------------------------------------------

        //[2007.03.13.화][추가!!!]
        //바로 아래의 _EDIT_CaretPos() 함수 안에서 _EditBuf_TExt() 함수가 처리되므로
        //이곳의 _Position() 함수안에서 _EditBuf_Text() 가 중복 처리되는 것을 막아 준다.
        if(pETCcontrol == true) _editbuf_text_no = true;
        //{
            _edit_caretpos_on = false;
            //{
                position--;
                ide_editor_Form->_scroll_v_Form->_Position(position);
            //}
            _edit_caretpos_on = true;
        //}
        if(pETCcontrol == true) _editbuf_text_no = false;

        //[실제 _position 변화값 구하기]
        //{
            //_position 값은 _min 보다 작을수 없으로 실제 지정한 값이 전부 그대로
            //적용되지 않을수 있으므로 여기서 실제 변화된 _position 값을 구한다.
            real_count = position_save - ide_editor_Form->_scroll_v_Form->_position;

            //변화된 행이 없는 경우는 처리하지 않는다.
            if(real_count <= 0)
            {
              _EDIT_CaretPos(_caret_x, _caret_y);

              //[2007.03.17.토][추가!!!]
              if(pETCcontrol == true) _EditBuf_Text();

              return;

            }
        //}
      }
  //}

  //[키동작]
  //{
      //[행 시작/끝]
      //{
          //---------------------------------------------------------------------
          //현재 이전행의 시작 index 값을 얻는다.
          STR_Get_BeforeLineStartIndex(_editbuf, _caretindex, &_linestartindex);
          STR_Get_ThisLineEndIndex(_editbuf, _linestartindex, &_lineendindex);
          //---------------------------------------------------------------------
      //}

      //[입력지정자 위치 조정]
      //{
          _CARETINDEXWIDTH_CaretIndex(_linestartindex, _lineendindex, &_caretindexwidth, &_caretindex, &_col);

          _caret_x  = _caretindexwidth;
          _caret_y -= _line_height;

          //[입력지정자] 위치는 [음수] 가 될수 없다.
          if(_caret_y < 0) { _caret_y = 0; }

          _EDIT_CaretPos(_caret_x, _caret_y);
      //}

      //[주의!!!][2007.03.16.금][추가!!!]
      //{
          //[입력지정자] 가 보이도록 스크롤 된 경우 _EditBuf_Text() 을 반드시 호출해서
          //다시 그려주어야 한다.
          if(pETCcontrol == true) _EditBuf_Text();
      //}
  //}

  //[선택영역처리][2007.02.09.금]
  //{
      //<shift> 키가 눌린 경우만 [선택영역] 구성을 처리해야 한다.
      if(_shift_down == true)
      {
        //둘다 -1 인 경우는 [선택영역] 을 처음 시작하는 것으로 본다.
        if((_select_start.caret_index == -1) && (_select_end.caret_index == -1))
        {
          //[선택영역] 시작 위치를 기록한다.(이동하기전 현재 위치이어야 한다.)
          //이미 변하기전 기록해 놓은 값을 사용한다.
          _Select_CaretIndex(&_select_start, caretindex); //_select_start.caret_index = caretindex;
          _select_start.caret_x     = caret_x;
          _select_start.caret_y     = caret_y;

          //[선택영역] 끝 위치를 초기화 한다.
          _Select_CaretIndex(&_select_end, -1); //_select_end.caret_index = -1;
          _select_end.caret_x     = 0;
          _select_end.caret_y     = 0;

        }

        //[선택영역] 이 생성중이다.
        _select_ing = true;

        //[선택영역 형성]
        //{
            //현재 위치를 [선택영역] 끝 위치로 기록한다.
            //이미 [키] 조작으로 변경된 [입력지정자] 위치가 끝위치가 된다.
            _Select_CaretIndex(&_select_end, _caretindex); //_select_end.caret_index = _caretindex;
            _select_end.caret_x     = _caret_x;
            _select_end.caret_y     = _caret_y;

            //[반영]
            //{
                //문서를 다시 출력하는 것으로 [선택영역] 이 자동반영 되도록 한다.
                _EditBuf_Text();
            //}
        //}
      }
  //}

  return;

}

void __fastcall Teditor_edit_Form::_KEY_Down(bool  pETCcontrol)
{
  //[2007.01.07.일][생성!!!]{-------------------------------------------------------------------------
  //[방향키-아래] 로 [입력지정자] 를 이동중 [편집기] 아랫 부분을 벗어나는 경우는
  //항상 [입력지정자] 가 가장 아랫행에 위치할수 있도록 자동으로 1행 아랫줄로 [스크롤] 해 주어야 한다.

  //[2007.02.09.금][추가!!!]
  //[키] 를 사용하여 [선택영역] 을 만드는 경우의 처리를 추가한다.

  //[2007.03.13.화][추가!!!]
  //순수하게 [입력지정자] 를 이동하는 경우는 먼저 _CARET_ViewAlways() 함수를 별도로 먼저
  //실행하게 되는데, 이 때 이 함수의 실행 결과에 따라서 _EditBuf_Text() 함수가 중복 처리되지
  //않도록 해 주어야 한다.
  //pETCcontrol 이 true 인 경우는 _EditBuf_Text() 를 처리하지 않게 만든다.
  //}-------------------------------------------------------------------------------------------------

  //[VAR]
  //{
      //현재 position 값.
      int  position       = ide_editor_Form->_scroll_v_Form->_position;

      //현재 값.
      int  position_save  = position;

      //실제 변화된 행수.
      int  real_count     = 0;

      //미리 [입력지정자] 의 위치를 비교를 위하여 산출한다.
      int  caret_next_pos = (_caret_y + _line_height);

      //변화하기 전의 현재 _caretindex 값을 저장해 놓는다.
      int  caretindex     = _caretindex;
      int  caret_x        = _caret_x;
      int  caret_y        = _caret_y;
  //}

  //[스크롤해야 하나?]
  //{
      //[입력지정자] 가 보이는 영역을 벗어 난 경우라면 아랫줄로 스크롤한다.
      if((_linetop_linenumber + ((this->Height - editor_info_Form->Height) / _line_height) - 1) < ( caret_next_pos / _line_height))
      {
        //[2007.03.13.화][추가!!!]
        //바로 아래의 _EDIT_CaretPos() 함수 안에서 _EditBuf_TExt() 함수가 처리되므로
        //이곳의 _Position() 함수안에서 _EditBuf_Text() 가 중복 처리되는 것을 막아 준다.
        if(pETCcontrol == true) _editbuf_text_no = true;
        //{
            _edit_caretpos_on = false;
            //{
                position++;
                ide_editor_Form->_scroll_v_Form->_Position(position);
            //}
            _edit_caretpos_on = true;
        //}
        if(pETCcontrol == true) _editbuf_text_no = false;

        //[실제 _position 변화값 구하기]
        //{
            //_position 값은 _max 보다 클수 없으로 실제 지정한 값이 전부 그대로
            //적용되지 않을수 있으므로 여기서 정확하게 변화된 _position 값을 구한다.
            real_count = ide_editor_Form->_scroll_v_Form->_position - position_save;

            //변화된 행이 없는 경우는 처리하지 앟는다.
            if(real_count <= 0)
            {
              _EDIT_CaretPos(_caret_x, _caret_y);

              //[2007.03.17.토][추가!!!]
              if(pETCcontrol == true) _EditBuf_Text();

              return;

            }
        //}
      }
  //}

  //[키동작]
  //{
      //[행 시작/끝]
      //{
          //-------------------------------------------------------------------
          //현재 다음행의 시작 index 값을 얻는다.
          STR_Get_NextLineStartIndex(_editbuf, _caretindex, &_linestartindex);
          STR_Get_ThisLineEndIndex(_editbuf, _linestartindex, &_lineendindex);
          //-------------------------------------------------------------------
      //}

      //[입력지정자 위치 조정]
      //{
          _CARETINDEXWIDTH_CaretIndex(_linestartindex, _lineendindex, &_caretindexwidth, &_caretindex, &_col);

          _caret_x  = _caretindexwidth;
          _caret_y += _line_height;

          //[입력지정자] 위치는 [문서] 전체 영역을 벗어나서는 안된다.
          if(_caret_y > (_line_height * (_linecount - 1))) { _caret_y = (_line_height * (_linecount - 1)); }

          _EDIT_CaretPos(_caret_x, _caret_y);
      //}

      //[주의!!!][2007.03.16.금][추가!!!]
      //{
          //[입력지정자] 가 보이도록 스크롤 된 경우 _EditBuf_Text() 을 반드시 호출해서
          //다시 그려주어야 한다.
          if(pETCcontrol == true) _EditBuf_Text();
      //}
  //}

  //[선택영역처리][2007.02.09.금]
  //{
      //<shift> 키가 눌린 경우만 [선택영역] 구성을 처리해야 한다.
      if(_shift_down == true)
      {
        //둘다 -1 인 경우는 [선택영역] 을 처음 시작하는 것으로 본다.
        if((_select_start.caret_index == -1) && (_select_end.caret_index == -1))
        {
          //[선택영역] 시작 위치를 기록한다.(이동하기전 현재 위치이어야 한다.)
          //이미 변하기전 기록해 놓은 값을 사용한다.
          _Select_CaretIndex(&_select_start, caretindex); //_select_start.caret_index = caretindex;
          _select_start.caret_x     = caret_x;
          _select_start.caret_y     = caret_y;

          //[선택영역] 끝 위치를 초기화 한다.
          _Select_CaretIndex(&_select_end, -1); //_select_end.caret_index = -1;
          _select_end.caret_x     = 0;
          _select_end.caret_y     = 0;

        }

        //[선택영역] 이 생성중이다.
        _select_ing = true;

        //[선택영역 형성]
        //{
            //현재 위치를 [선택영역] 끝 위치로 기록한다.
            //이미 [키] 조작으로 변경된 [입력지정자] 위치가 끝위치가 된다.
            _Select_CaretIndex(&_select_end, _caretindex); //_select_end.caret_index = _caretindex;
            _select_end.caret_x     = _caret_x;
            _select_end.caret_y     = _caret_y;

            //[반영]
            //{
                //문서를 다시 출력하는 것으로 [선택영역] 이 자동반영 되도록 한다.
                _EditBuf_Text();
            //}
        //}
      }
  //}

  return;

}

void __fastcall Teditor_edit_Form::_KEY_Left(bool  pETCcontrol)
{
  //[2007.01.07.일][생성!!!]{------------------------------------------------------------------------------------
  //[방향키-왼] 로 [입력지정자] 를 이동중 [편집기] 왼쪽 부분을 벗어나는 경우는
  //항상 [입력지정자] 가 가장 왼쪽에 위치할수 있도록 자동으로 1열 왼쪽으로 [스크롤] 해 주어야 한다.
  //[한글/영문] 에따라 폭이 달라지나, 기본적으로 [수평스크롤] 은 [영문] 자의 폭을 기준으로 처리
  //되므로 한글의 경우는 [영문]*2 의 폭으로 처리되어야 한다.

  //[2007.02.10.토][추가!!!]
  //[키] 를 사용하여 [선택영역] 을 만드는 경우의 처리를 추가한다.

  //[2007.03.14.수][추가!!!]
  //순수하게 [입력지정자] 를 이동하는 경우 먼저 _CARET_ViewAlways() 함수를 별도로 먼저
  //실행하게 되는데, 이 때 _CARET_ViewAlways() 함수가 처리 된 경우는 _CARET_ViewAlways() 함수
  //내부적으로 _EditBuf_Text() 함수가 실행되지 않도록 하였다.(이는 중복 실행으로인한 깜박임 방지를 위한 것이다.)
  //따라서, pETCcontrol 이 true 인 경우는 _EditBuf_Text() 를 끝에서 한번은 반드시 처리해 주어야 한다.
  //}------------------------------------------------------------------------------------------------------------

  //[주의!!!][2007.01.14.일]
  //{
      //-------------------------------------------------------------------------------------
      //한글은 첫 byte 만 [음수] 가 아니라 2byte 각각 모두 음수이다.
      //이점을 주의해야 한다.
      //단, '똠' 과 같은 문자가 입력되는 경우는 자동으로 OS 가 [조합형코드] 로
      //바꾸어서 전달하는데 이 [조함형코드] 는 무조건 찻 byte 가 [음수] 이다.
      //따라서 [한글/영문] 을 구분하기 위해서는 반드시 첫 byte 가 [음수] 인지 확인해야 한다.
      //이는 순서대로 처리할때는 문제가 없으나, 역방향으로 버퍼를 거꾸로 검사하는 경우는
      //반드시 첫 byte 가 [음수] 인지 확인해 보아야 한다.
      //-------------------------------------------------------------------------------------
  //}

  //[VAR]
  //{
      //현재 position 값.
      int  position       = ide_editor_Form->_scroll_h_Form->_position;

      //현재 값.
      int  position_save  = position;

      //실제 변화된 행수.
      int  real_count     = 0;
      
      //변화하기 전의 현재 _caretindex 값을 저장해 놓는다.
      int  caretindex     = _caretindex;
      int  caret_x        = _caret_x;
      int  caret_y        = _caret_y;
  //}

  //[키동작]
  //{
      //[행 시작/끝]
      //{
          //-------------------------------------------------------------------
          STR_Get_ThisLineStartIndex(_editbuf, _caretindex, &_linestartindex);
          STR_Get_ThisLineEndIndex(_editbuf, _linestartindex, &_lineendindex);
          //-------------------------------------------------------------------
      //}

      //[입력지정자 위치 조정]
      //{
          _CARETINDEX_MoveLeft(_linestartindex, &_caretindex);
          _CARETINDEX_CaretIndexWidth(_linestartindex, _caretindex, &_caretindexwidth, &_col);

          _caret_x = _caretindexwidth;

          //여기서는 스크롤 하지 않아야 한다.
          _edit_caretpos_on = false;
          //{
              _EDIT_CaretPos(_caret_x, _caret_y);
          //}
          _edit_caretpos_on = true;
      //}
  //}

  //[선택영역처리][2007.02.10.토]
  //{
      //<shift> 키가 눌린 경우만 [선택영역] 구성을 처리해야 한다.
      if(_shift_down == true)
      {
        //둘다 -1 인 경우는 [선택영역] 을 처음 시작하는 것으로 본다.
        if((_select_start.caret_index == -1) && (_select_end.caret_index == -1))
        {
          //[선택영역] 시작 위치를 기록한다.(이동하기전 현재 위치이어야 한다.)
          //이미 변하기전 기록해 놓은 값을 사용한다.
          _Select_CaretIndex(&_select_start, caretindex); //_select_start.caret_index = caretindex;
          _select_start.caret_x     = caret_x;
          _select_start.caret_y     = caret_y;

          //[선택영역] 끝 위치를 초기화 한다.
          _Select_CaretIndex(&_select_end, -1); //_select_end.caret_index = -1;
          _select_end.caret_x     = 0;
          _select_end.caret_y     = 0;

        }

        //[선택영역] 이 생성중이다.
        _select_ing = true;

        //[선택영역 형성]
        //{
            //현재 위치를 [선택영역] 끝 위치로 기록한다.
            //이미 [키] 조작으로 변경된 [입력지정자] 위치가 끝위치가 된다.
            _Select_CaretIndex(&_select_end, _caretindex); //_select_end.caret_index = _caretindex;
            _select_end.caret_x     = _caret_x;
            _select_end.caret_y     = _caret_y;

            //[반영]
            //{
                //문서를 다시 출력하는 것으로 [선택영역] 이 자동반영 되도록 한다.
                _EditBuf_Text();
            //}
        //}
      }
  //}

  //[스크롤해야 하나?]
  //{
      //[입력지정자] 가 보이는 영역을 벗어 난 경우라면 왼쪽으로 스크롤한다.
      if((_text_org_x - d_gutter_width + _caret_x) < 0)
      {
        //[한글/영문?]
        //{
            //---------------------------------------------------------------------------------------------
            //현재 _caretindex 위치의 문자가 [한글/영문] 에 따라 스크롤 값이 달라야 한다.
            //위에서 이미 _caretindex 에 해당하는 문자를 건너서 이동한 것이므로 이 폭을가지고 따져야 한다.

            if     (_editbuf[_caretindex] > 0)
            {
              //[영문] 인 경우는 [영문폭] 로 이동해야 하므로 -1 만큼 스크롤 한다.
              position -= 1;

            }
            else if(_editbuf[_caretindex] < 0)
            {
              //[한글] 인 경우는 [영문폭*2] 로 이동해야 하므로 -2 만큼 스크롤 한다.
              position -= 2;

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

        //지정 양만큼 수평으로 스크롤 한다.
        ide_editor_Form->_scroll_h_Form->_Position(position);

        //[실제 _position 변화값 구하기]
        //{
            //-----------------------------------------------------------------------
            //_position 값은 _max 보다 클수 없으로 실제 지정한 값이 전부 그대로
            //적용되지 않을수 있으므로 여기서 정확하게 변화된 _position 값을 구한다.
            real_count = ide_editor_Form->_scroll_h_Form->_position - position_save;

            //변화된 행이 없는 경우는 처리하지 앟는다.
            if(real_count <= 0) return;
            //-----------------------------------------------------------------------
        //}
      }
      else
      {
        //[스크롤] 하지 않는 경우라면 _EDIT_CaretPos() 함수로 [입력지정자] 를 현재 위치 시켜야 한다.
        //이는 위에서 [스크롤] 되는 경우 _EDIT_CaretPos() 함수의 중복 사용을 막기 위하여 처리하지 않았기 때문이다.
        _EDIT_CaretPos(_caret_x, _caret_y);

        //[2007.03.14.수][추가!!!]
        if(pETCcontrol == true) _EditBuf_Text();

      }
  //}

  return;

}

void __fastcall Teditor_edit_Form::_KEY_Right(bool  pETCcontrol,
                                              bool  pSELECTtrue)
{
  //[2007.01.07.일][생성!!!]{------------------------------------------------------------------------------------
  //[방향키-오른] 로 [입력지정자] 를 이동중 [편집기] 오른쪽 부분을 벗어나는 경우는
  //항상 [입력지정자] 가 가장 오른쪽에 위치할수 있도록 자동으로 1열 오른쪽으로 [스크롤] 해 주어야 한다.
  //[한글/영문] 에따라 폭이 달라지나, 기본적으로 [수평스크롤] 은 [영문] 자의 폭을 기준으로 처리
  //되므로 한글의 경우는 [영문]*2 의 폭으로 처리되어야 한다.
  //
  //[2007.02.10.토][추가!!!]-------------------------------------------------------------------------------------
  //[키] 를 사용하여 [선택영역] 을 만드는 경우의 처리를 추가한다.
  //
  //[2007.02.21.수][수정!!!]
  //_CARET_MOONJA_Insert() 함수에서 일반 문자를 출력하는 경우 문자 출력후 [입력지정자] 의 이동을 위하여
  //이 함수를 사용하는데 <Shift-Key> 를 눌러서 [대문자] 를 입력하는 경우 [선택영역] 을 생성하는것으로
  //취급될수 있다. 따라서, 이 경우는 [선택영역] 처리를 하지 않아야 한다.
  //pSELECTtrue == true  : [선택영역] 생성도 처리한다.
  //            == false : [선택영역] 을 처리하지 않는다. (순수 키 처리만 수행한다)
  //
  //[2007.03.14.수][추가!!!]-------------------------------------------------------------------------------------
  //순수하게 [입력지정자] 를 이동하는 경우 먼저 _CARET_ViewAlways() 함수를 별도로 먼저
  //실행하게 되는데, 이 때 _CARET_ViewAlways() 함수가 처리 된 경우는 _CARET_ViewAlways() 함수
  //내부적으로 _EditBuf_Text() 함수가 실행되지 않도록 하였다.(이는 중복 실행으로인한 깜박임 방지를 위한 것이다.)
  //따라서, pETCcontrol 이 true 인 경우는 _EditBuf_Text() 를 끝에서 한번은 반드시 처리해 주어야 한다.
  //}------------------------------------------------------------------------------------------------------------

  //[주의!!!][2007.01.14.일]{------------------------------------------------------------
  //한글은 첫 byte 만 [음수] 가 아니라 2 byte 각각 모두 음수이다.
  //이점을 주의해야 한다.
  //단, '똠' 과 같은 문자가 입력되는 경우는 자동으로 OS 가 [조합형코드] 로
  //바꾸어서 전달하는데 이 [조함형코드] 는 무조건 찻 byte 가 [음수] 이다.
  //따라서 [한글/영문] 을 구분하기 위해서는 반드시 첫 byte 가 [음수] 인지 확인해야 한다.
  //이는 순서대로 처리할때는 문제가 없으나, 역방향으로 버퍼를 거꾸로 검사하는 경우는
  //반드시 첫 byte 가 [음수] 인지 확인해 보아야 한다.
  //}------------------------------------------------------------------------------------

  //[VAR]
  //{
      //현재 position 값.
      int  position        = ide_editor_Form->_scroll_h_Form->_position;

      //현재 값.
      int  position_save   = position;

      //실제 변화된 행수.
      int  real_count      = 0;

      int  caretindex_save = _caretindex;

      //변화하기 전의 현재 _caretindex 값을 저장해 놓는다.
      int  caretindex      = _caretindex;
      int  caret_x         = _caret_x;
      int  caret_y         = _caret_y;

  //}

  //[키동작]
  //{
      //[행 시작/끝]
      //{
          //-------------------------------------------------------------------
          STR_Get_ThisLineStartIndex(_editbuf, _caretindex, &_linestartindex);
          STR_Get_ThisLineEndIndex(_editbuf, _linestartindex, &_lineendindex);
          //-------------------------------------------------------------------
      //}

      //[입력지정자 위치 조정]
      //{
          _CARETINDEX_MoveRight(_lineendindex, &_caretindex);
          _CARETINDEX_CaretIndexWidth(_linestartindex, _caretindex, &_caretindexwidth, &_col);

          _caret_x = _caretindexwidth;

          //여기서는 스크롤 하지 않아야 한다.
          _edit_caretpos_on = false;
          //{
              _EDIT_CaretPos(_caret_x, _caret_y);
          //}
          _edit_caretpos_on = true;
      //}
  //}

  //[선택영역처리][2007.02.10.토]
  //{
      //<shift> 키가 눌린 경우만 [선택영역] 구성을 처리해야 한다.
      if((pSELECTtrue == true) && (_shift_down == true))
      {
        //둘다 -1 인 경우는 [선택영역] 을 처음 시작하는 것으로 본다.
        if((_select_start.caret_index == -1) && (_select_end.caret_index == -1))
        {
          //[선택영역] 시작 위치를 기록한다.(이동하기전 현재 위치이어야 한다.)
          //이미 변하기전 기록해 놓은 값을 사용한다.
          _Select_CaretIndex(&_select_start, caretindex); //_select_start.caret_index = caretindex;
          _select_start.caret_x     = caret_x;
          _select_start.caret_y     = caret_y;

          //[선택영역] 끝 위치를 초기화 한다.
          _Select_CaretIndex(&_select_end, -1); //_select_end.caret_index = -1;
          _select_end.caret_x     = 0;
          _select_end.caret_y     = 0;

        }

        //[선택영역] 이 생성중이다.
        _select_ing = true;

        //[선택영역 형성]
        //{
            //현재 위치를 [선택영역] 끝 위치로 기록한다.
            //이미 [키] 조작으로 변경된 [입력지정자] 위치가 끝위치가 된다.
            _Select_CaretIndex(&_select_end, _caretindex); //_select_end.caret_index = _caretindex;
            _select_end.caret_x     = _caret_x;
            _select_end.caret_y     = _caret_y;

            //[반영]
            //{
                //문서를 다시 출력하는 것으로 [선택영역] 이 자동반영 되도록 한다.
                _EditBuf_Text();
            //}
        //}
      }
  //}

  //[스크롤해야 하나?]
  //{
      //[입력지정자] 가 보이는 영역을 벗어 난 경우라면 왼쪽으로 스크롤한다.
      //[한문자] 폭의 여유를 둔다.--------v
      if((_text_org_x + _caret_x + _font_eng_width) > (this->Width - ide_editor_Form->_scroll_v_Form->Width))
      {
        //[한글/영문?]
        //{
            //--------------------------------------------------------------------------------------------------
            //현재 _caretindex 위치의 문자가 [한글/영문] 에 따라 스크롤 값이 달라야 한다.
            //위에서 이미 _caretindex 에 해당하는 문자를 건너서 이동한 것이므로 이동하기 전의  위치로 검사한다.
            if     (_editbuf[caretindex_save] > 0)
            {
              //[영문] 인 경우는 [영문폭] 로 이동해야 하므로 +1 만큼 스크롤 한다.
              position += 1;

            }
            else if(_editbuf[caretindex_save] < 0)
            {
              //[한글] 인 경우는 [영문폭*2] 로 이동해야 하므로 +2 만큼 스크롤 한다.
              position += 2;

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

        //지정 양만큼 수평으로 스크롤 한다.
        ide_editor_Form->_scroll_h_Form->_Position(position);

        //[실제 _position 변화값 구하기]
        //{
            //-----------------------------------------------------------------------
            //_position 값은 _max 보다 클수 없으로 실제 지정한 값이 전부 그대로
            //적용되지 않을수 있으므로 여기서 정확하게 변화된 _position 값을 구한다.
            real_count = position_save - ide_editor_Form->_scroll_h_Form->_position;

            //변화된 행이 없는 경우는 처리하지 앟는다.
            if(real_count <= 0) return;
            //-----------------------------------------------------------------------
        //}
      }
      else
      {
        //[스크롤] 하지 않는 경우라면 _EDIT_CaretPos() 함수로 [입력지정자] 를 현재 위치 시켜야 한다.
        //이는 위에서 [스크롤] 되는 경우 _EDIT_CaretPos() 함수의 중복 사용을 막기 위하여 처리하지 않았기 때문이다.
        _EDIT_CaretPos(_caret_x, _caret_y);

        //[2007.03.14.수][추가!!!]
        if(pETCcontrol == true) _EditBuf_Text();

      }
  //}

  return;

}

void __fastcall Teditor_edit_Form::_KEY_Home(bool  pETCcontrol)
{
  //[2007.01.07.일][생성!!!]{------------------------------------------------------------
  //이미 [수평스크롤] 상태인 경우는 [편집기] 가장 왼쪽에 [입력지정자] 가 위치할수 있도록
  //자동으로 가장 왼쪽으로 [스크롤] 한다. (무조선 _position = 0 인 위치로 이동)

  //[2007.02.10.토][추가!!!]
  //[키] 를 사용하여 [선택영역] 을 만드는 경우의 처리를 추가한다.

  //[2007.03.14.수][추가!!!]
  //순수하게 [입력지정자] 를 이동하는 경우는 먼저 _CARET_ViewAlways() 함수를 별도로 먼저
  //실행하게 되는데, 이 때 이 함수의 실행 결과에 따라서 _EditBuf_Text() 함수가 중복 처리되지
  //않도록 해 주어야 한다.
  //pETCcontrol 이 true 인 경우는 _EditBuf_Text() 를 처리하지 않게 만든다.
  //}------------------------------------------------------------------------------------

  //[VAR]
  //{
      //변화하기 전의 현재 _caretindex 값을 저장해 놓는다.
      int  caretindex = _caretindex;
      int  caret_x    = _caret_x;
      int  caret_y    = _caret_y;
  //}

  //[스크롤]
  //{
      //문조건 첫 열이 보이도록 스크롤 한다.
      //단, 시간낭비를 막기 위하여 이미 _position == 0 인 경우는 처리하지 않아야 한다.
      if(ide_editor_Form->_scroll_h_Form->_position > 0)
      {
        //[2007.03.14.수][추가!!!]
        //[선택영역] 이 있는 경우는 바로 아래의 _EDIT_CaretPos() 함수 안에서
        //해제 되기 전의 모습이 보이게 되어 깜박거리는 문제가 발생하므로 여기서는
        //이곳의 _Position() 함수안에서 _EditBuf_Text() 가 중복 처리되는 것을 막아 준다.
        if(pETCcontrol == true) _editbuf_text_no = true;
        //{
            //여기서는 스크롤 하지 않아야 한다.
            _edit_caretpos_on = false;
            //{
                ide_editor_Form->_scroll_h_Form->_Position(0);
            //}
            _edit_caretpos_on = true;
        //}
        if(pETCcontrol == true) _editbuf_text_no = false;
      }
  //}

  //[행 시작 위치]
  //{
      //-------------------------------------------------------------------
      STR_Get_ThisLineStartIndex(_editbuf, _caretindex, &_linestartindex);
      //-------------------------------------------------------------------
  //}

  //[키동작]
  //{
      //[입력지정자 위치 조정]
      //{
          _caretindex = _linestartindex;
          _CARETINDEX_CaretIndexWidth(_linestartindex, _caretindex, &_caretindexwidth, &_col);

          _caret_x = _caretindexwidth;
          _EDIT_CaretPos(_caret_x, _caret_y);
      //}

      //[2007.03.14.수][추가!!!]
      //이 경우는 반드시 _EditBuf_Text() 를 처리해 주어야 한다.
      //단, [선택영역] 이 있는 경우는 위에서 완전히 해제 된 다음에 그려져야 하므로
      //반드시 이 위치에서 _EditBuf_Text() 함수로 다시 그려야 한다.
      if(pETCcontrol == true) _EditBuf_Text();
  //}

  //[선택영역처리][2007.02.10.토]
  //{
      //<shift> 키가 눌린 경우만 [선택영역] 구성을 처리해야 한다.
      if(_shift_down == true)
      {
        //둘다 -1 인 경우는 [선택영역] 을 처음 시작하는 것으로 본다.
        if((_select_start.caret_index == -1) && (_select_end.caret_index == -1))
        {
          //[선택영역] 시작 위치를 기록한다.(이동하기전 현재 위치이어야 한다.)
          //이미 변하기전 기록해 놓은 값을 사용한다.
          _Select_CaretIndex(&_select_start, caretindex); //_select_start.caret_index = caretindex;
          _select_start.caret_x     = caret_x;
          _select_start.caret_y     = caret_y;

          //[선택영역] 끝 위치를 초기화 한다.
          _Select_CaretIndex(&_select_end, -1); //_select_end.caret_index = -1;
          _select_end.caret_x     = 0;
          _select_end.caret_y     = 0;

        }

        //[선택영역] 이 생성중이다.
        _select_ing = true;

        //[선택영역 형성]
        //{
            //현재 위치를 [선택영역] 끝 위치로 기록한다.
            //이미 [키] 조작으로 변경된 [입력지정자] 위치가 끝위치가 된다.
            _Select_CaretIndex(&_select_end, _caretindex); //_select_end.caret_index = _caretindex;
            _select_end.caret_x     = _caret_x;
            _select_end.caret_y     = _caret_y;

            //[반영]
            //{
                //문서를 다시 출력하는 것으로 [선택영역] 이 자동반영 되도록 한다.
                _EditBuf_Text();
            //}
        //}
      }
  //}

  return;

}

void __fastcall Teditor_edit_Form::_KEY_End(bool  pETCcontrol)
{
  //[2007.01.07.일][생성!!!]{-------------------------------------------------------------------
  //현재 행 끝에 있는 [입력지정자] 가 [편집기] 가장 오른쪽에 위치하도록 [수평스크롤] 을 해준다.

  //[2007.02.10.토][추가!!!]
  //[키] 를 사용하여 [선택영역] 을 만드는 경우의 처리를 추가한다.
  //}-------------------------------------------------------------------------------------------

  //[VAR]
  //{
      //현재 position 값.
      int  position      = ide_editor_Form->_scroll_h_Form->_position;

      //현재 값.
      int  position_save = position;

      //실제 변화된 행수.
      int  real_count    = 0;

      //변화하기 전의 현재 _caretindex 값을 저장해 놓는다.
      int  caretindex    = _caretindex;
      int  caret_x       = _caret_x;
      int  caret_y       = _caret_y;
  //}

  //[키동작]
  //{
      //[입력지정자 위치 조정]
      //{
          //이행의 끝 위치를 구한다.(여기서 직접 구하는 것이 정확하다.)
          STR_Get_ThisLineEndIndex(_editbuf, _caretindex, &_lineendindex);

          _caretindex = _lineendindex;
          _CARETINDEX_CaretIndexWidth(_linestartindex, _caretindex, &_caretindexwidth, &_col);

          _caret_x = _caretindexwidth;

          //여기서는 스크롤 하지 않아야 한다.
          _edit_caretpos_on = false;
          //{
              _EDIT_CaretPos(_caret_x, _caret_y);
          //}
          _edit_caretpos_on = true;
      //}
  //}

  //[선택영역처리][2007.02.10.토]
  //{
      //<shift> 키가 눌린 경우만 [선택영역] 구성을 처리해야 한다.
      if(_shift_down == true)
      {
        //둘다 -1 인 경우는 [선택영역] 을 처음 시작하는 것으로 본다.
        if((_select_start.caret_index == -1) && (_select_end.caret_index == -1))
        {
          //[선택영역] 시작 위치를 기록한다.(이동하기전 현재 위치이어야 한다.)
          //이미 변하기전 기록해 놓은 값을 사용한다.
          _Select_CaretIndex(&_select_start, caretindex); //_select_start.caret_index = caretindex;
          _select_start.caret_x     = caret_x;
          _select_start.caret_y     = caret_y;

          //[선택영역] 끝 위치를 초기화 한다.
          _Select_CaretIndex(&_select_end, -1); //_select_end.caret_index = -1;
          _select_end.caret_x     = 0;
          _select_end.caret_y     = 0;

        }

        //[선택영역] 이 생성중이다.
        _select_ing = true;

        //[선택영역 형성]
        //{
            //현재 위치를 [선택영역] 끝 위치로 기록한다.
            //이미 [키] 조작으로 변경된 [입력지정자] 위치가 끝위치가 된다.
            _Select_CaretIndex(&_select_end, _caretindex); //_select_end.caret_index = _caretindex;
            _select_end.caret_x     = _caret_x;
            _select_end.caret_y     = _caret_y;

            //[반영]
            //{
                //문서를 다시 출력하는 것으로 [선택영역] 이 자동반영 되도록 한다.
                _EditBuf_Text();
            //}
        //}
      }
  //}

  //[스크롤]
  //{
      //[입력지정자] 가 보이는 영역을 벗어 난 경우라면 왼쪽으로 스크롤한다.
      //[한문자] 폭의 여유를 둔다.--------v
      if((_text_org_x + _caret_x + _font_eng_width) > (this->Width - ide_editor_Form->_scroll_v_Form->Width))
      {
        //[2007.03.14.수][추가!!!]
        //[선택영역] 이 있는 경우는 바로 아래의 _EDIT_CaretPos() 함수 안에서
        //해제 되기 전의 모습이 보이게 되어 깜박거리는 문제가 발생하므로 여기서는
        //이곳의 _Position() 함수안에서 _EditBuf_Text() 가 중복 처리되는 것을 막아 준다.
        if(pETCcontrol == true) _editbuf_text_no = true;
        //{
            //[스크롤 양 계산]
            //{
                position += (((_text_org_x + _caret_x + _font_eng_width) -
                             //약간의 여유 값을 준다.----------------------------------------------------v
                             (this->Width - ide_editor_Form->_scroll_v_Form->Width)) / _font_eng_width + 1);
            //}

            //지정 양만큼 수평으로 스크롤 한다.
            ide_editor_Form->_scroll_h_Form->_Position(position);
        //}
        if(pETCcontrol == true) _editbuf_text_no = false;

        //[실제 _position 변화값 구하기]
        //{
            //-----------------------------------------------------------------------
            //_position 값은 _max 보다 클수 없으로 실제 지정한 값이 전부 그대로
            //적용되지 않을수 있으므로 여기서 정확하게 변화된 _position 값을 구한다.
            real_count = position_save - ide_editor_Form->_scroll_h_Form->_position;

            //변화된 행이 없는 경우는 처리하지 앟는다.
            if(real_count <= 0)
            {
              _EDIT_CaretPos(_caret_x, _caret_y);

              //[2007.03.14.수][추가!!!]
              if(pETCcontrol == true) _EditBuf_Text();

              return;
              
            }
            //-----------------------------------------------------------------------
        //}
      }
      else
      {
        //[스크롤] 하지 않는 경우라면 _EDIT_CaretPos() 함수로 [입력지정자] 를 현재 위치 시켜야 한다.
        //이는 위에서 [스크롤] 되는 경우 _EDIT_CaretPos() 함수의 중복 사용을 막기 위하여 처리하지 않았기 때문이다.
        _EDIT_CaretPos(_caret_x, _caret_y);

        //[2007.03.14.수][추가!!!]
        if(pETCcontrol == true) _EditBuf_Text();

      }
  //}

  return;

}

void __fastcall Teditor_edit_Form::_KEY_PageUp(void)
{
  //[2006.12.29.금][생성!!!]{------------------------------------------
  //[1쪽]  단위로 위로 이동을 하되 [입력지정자] 도 같이 이동해야 한다.
  //이 경우 _caretindex 등 기본정보도 다 수정되어야 한다.
  //이 함수는 [PageUP-KEY] 를 누르는 경우 호출된다.

  //[2007.02.10.토][추가!!!]
  //[키] 를 사용하여 [선택영역] 을 만드는 경우의 처리를 추가한다.
  //}------------------------------------------------------------------

  //[VAR]
  //{
      //현재 position 값.
      int  position       = ide_editor_Form->_scroll_v_Form->_position;
      //현재 값.
      int  position_save  = position;

      //변화되는 position 값.(이상적인 값)
      int  position_count = ((this->Height - editor_info_Form->Height) / _line_height);

      //실제 변화된 행수.
      int  real_count     = 0;

      int  i;

      //변화하기 전의 현재 _caretindex 값을 저장해 놓는다.
      int  caretindex     = _caretindex;
      int  caret_x        = _caret_x;
      int  caret_y        = _caret_y;
  //}

  //[스크롤]
  //{
      _editbuf_text_no = true;
      //{
          position -= position_count;
          ide_editor_Form->_scroll_v_Form->_Position(position);
      //}
      _editbuf_text_no = false;

      //[실제 _position 변화값 구하기]
      //{
          //_position 값은 _min 보다 작을수 없으로 실제 지정한 값이 전부 그대로
          //적용되지 않을수 있으므로 여기서 정확하게 변화된 _position 값을 구한다.
          real_count = position_save - ide_editor_Form->_scroll_v_Form->_position;

          //변화된 행이 없는 경우는 처리하지 앟는다.
          if(real_count <= 0)
          {
            _editbuf_text_no = true;
            //{
                _EDIT_CaretPos(_caret_x, _caret_y);
            //}
            _editbuf_text_no = false;

            _EditBuf_Text();

            return;

          }
      //}
  //}

  //[스크롤 동기화]{-----------------------------------------------------
  //_Position() 함수를 호출하면 자동으로 _EVENT_V_Scroll() 가 호출되므로
  //[문서] 는 자동으로 [스크롤] 에 동기화 된다.
  //}--------------------------------------------------------------------

  //[입력지정자]
  //{
      //PageUp 인 경우는 이전행으로 [스크롤] 한 경우다.

      //[행 시작/끝]
      //{
          //[입력지정자] 가 위치할 행의 시작위치를 구한다.
          for(i = 0; i < real_count; i++)
          {
            //계속 이전행을 처리하는 것으로 값을 구한다.
            STR_Get_BeforeLineStartIndex(_editbuf, _linestartindex, &_linestartindex);

          }

          //이행의 끝 위치를 구한다.
          STR_Get_ThisLineEndIndex(_editbuf, _linestartindex, &_lineendindex);
      //}

      //[입력지정자 위치 조정]
      //{
          _CARETINDEXWIDTH_CaretIndex(_linestartindex, _lineendindex, &_caretindexwidth, &_caretindex, &_col);

          _caret_x  = _caretindexwidth;
          _caret_y -= (real_count * _line_height);

          _EDIT_CaretPos(_caret_x, _caret_y);

          if(_shift_down != true)
          {
            //true 인 경우는 바로 아래에서 다시 그려주게 되므로 중복을 방지하기 위하여
            //여기서는 처리하지 않아야 한다.
            _EditBuf_Text();

          }
      //}
  //}

  //[선택영역처리][2007.02.10.토]
  //{
      //<shift> 키가 눌린 경우만 [선택영역] 구성을 처리해야 한다.
      if(_shift_down == true)
      {
        //둘다 -1 인 경우는 [선택영역] 을 처음 시작하는 것으로 본다.
        if((_select_start.caret_index == -1) && (_select_end.caret_index == -1))
        {
          //[선택영역] 시작 위치를 기록한다.(이동하기전 현재 위치이어야 한다.)
          //이미 변하기전 기록해 놓은 값을 사용한다.
          _Select_CaretIndex(&_select_start, caretindex); //_select_start.caret_index = caretindex;
          _select_start.caret_x     = caret_x;
          _select_start.caret_y     = caret_y;

          //[선택영역] 끝 위치를 초기화 한다.
          _Select_CaretIndex(&_select_end, -1); //_select_end.caret_index = -1;
          _select_end.caret_x     = 0;
          _select_end.caret_y     = 0;

        }

        //[선택영역] 이 생성중이다.
        _select_ing = true;

        //[선택영역 형성]
        //{
            //현재 위치를 [선택영역] 끝 위치로 기록한다.
            //이미 [키] 조작으로 변경된 [입력지정자] 위치가 끝위치가 된다.
            _Select_CaretIndex(&_select_end, _caretindex); //_select_end.caret_index = _caretindex;
            _select_end.caret_x     = _caret_x;
            _select_end.caret_y     = _caret_y;

            //[반영]
            //{
                //문서를 다시 출력하는 것으로 [선택영역] 이 자동반영 되도록 한다.
                _EditBuf_Text();
            //}
        //}
      }
  //}

  return;

}

void __fastcall Teditor_edit_Form::_KEY_PageDown(void)
{
  //[2006.12.30.토][생성!!!]{--------------------------------------------
  //[1쪽]  단위로 아래로 이동을 하되 [입력지정자] 도 같이 이동해야 한다.
  //이 경우 _caretindex 등 기본정보도 다 수정되어야 한다.
  //이 함수는 [PageDown-KEY] 를 누르는 경우 호출된다.

  //[2007.02.10.토][추가!!!]
  //[키] 를 사용하여 [선택영역] 을 만드는 경우의 처리를 추가한다.
  //}--------------------------------------------------------------------

  //[VAR]
  //{
      //현재 position 값.
      int  position       = ide_editor_Form->_scroll_v_Form->_position;
      //현재 값.
      int  position_save  = position;

      //변화되는 position 값.(이상적인 값)
      int  position_count = ((this->Height - editor_info_Form->Height) / _line_height);

      //실제 변화된 행수.
      int  real_count     = 0;

      int  i;

      //변화하기 전의 현재 _caretindex 값을 저장해 놓는다.
      int  caretindex     = _caretindex;
      int  caret_x        = _caret_x;
      int  caret_y        = _caret_y;
  //}

  //[스크롤]
  //{
      _editbuf_text_no = true;
      //{
          position += position_count;
          ide_editor_Form->_scroll_v_Form->_Position(position);
      //}
      _editbuf_text_no = false;

      //[실제 _position 변화값 구하기]
      //{
          //_position 값은 _max 보다 클수 없으로 실제 지정한 값이 전부 그대로
          //적용되지 않을수 있으므로 여기서 정확하게 변화된 _position 값을 구한다.
          real_count = ide_editor_Form->_scroll_v_Form->_position - position_save;

          //변화된 행이 없는 경우는 처리하지 않는다.
          if(real_count <= 0)
          {
            _editbuf_text_no = true;
            //{
                _EDIT_CaretPos(_caret_x, _caret_y);
            //}
            _editbuf_text_no = false;

            _EditBuf_Text();

            return;

          }
      //}
  //}

  //[스크롤 동기화]{-----------------------------------------------------
  //_Position() 함수를 호출하면 자동으로 _EVENT_V_Scroll() 가 호출되므로
  //[문서] 는 자동으로 [스크롤] 에 동기화 된다.
  //}--------------------------------------------------------------------

  //[입력지정자]
  //{
      //PageUp 인 경우는 이전행으로 [스크롤] 한 경우다.

      //[행 시작/끝]
      //{
          //[입력지정자] 가 위치할 행의 시작위치를 구한다.
          for(i = 0; i < real_count; i++)
          {
            //계속 이전행을 처리하는 것으로 값을 구한다.
            STR_Get_NextLineStartIndex(_editbuf, _linestartindex, &_linestartindex);

          }

          //이행의 끝 위치를 구한다.
          STR_Get_ThisLineEndIndex(_editbuf, _linestartindex, &_lineendindex);
      //}

      //[입력지정자 위치 조정]
      //{
          _CARETINDEXWIDTH_CaretIndex(_linestartindex, _lineendindex, &_caretindexwidth, &_caretindex, &_col);

          _caret_x  = _caretindexwidth;
          _caret_y += (real_count * _line_height);

          _EDIT_CaretPos(_caret_x, _caret_y);

          if(_shift_down != true)
          {
            //true 인 경우는 바로 아래에서 다시 그려주게 되므로 중복을 방지하기 위하여
            //여기서는 처리하지 않아야 한다.
            _EditBuf_Text();

          }
      //}
  //}

  //[선택영역처리][2007.02.10.토]
  //{
      //<shift> 키가 눌린 경우만 [선택영역] 구성을 처리해야 한다.
      if(_shift_down == true)
      {
        //둘다 -1 인 경우는 [선택영역] 을 처음 시작하는 것으로 본다.
        if((_select_start.caret_index == -1) && (_select_end.caret_index == -1))
        {
          //[선택영역] 시작 위치를 기록한다.(이동하기전 현재 위치이어야 한다.)
          //이미 변하기전 기록해 놓은 값을 사용한다.
          _Select_CaretIndex(&_select_start, caretindex); //_select_start.caret_index = caretindex;
          _select_start.caret_x     = caret_x;
          _select_start.caret_y     = caret_y;

          //[선택영역] 끝 위치를 초기화 한다.
          _Select_CaretIndex(&_select_end, -1); //_select_end.caret_index = -1;
          _select_end.caret_x     = 0;
          _select_end.caret_y     = 0;

        }

        //[선택영역] 이 생성중이다.
        _select_ing = true;

        //[선택영역 형성]
        //{
            //현재 위치를 [선택영역] 끝 위치로 기록한다.
            //이미 [키] 조작으로 변경된 [입력지정자] 위치가 끝위치가 된다.
            _Select_CaretIndex(&_select_end, _caretindex); //_select_end.caret_index = _caretindex;
            _select_end.caret_x     = _caret_x;
            _select_end.caret_y     = _caret_y;

            //[반영]
            //{
                //문서를 다시 출력하는 것으로 [선택영역] 이 자동반영 되도록 한다.
                _EditBuf_Text();

            //}

        //}

      }

  //}

  return;

}

void __fastcall Teditor_edit_Form::_KEY_Enter(//[수정이력] 을 적용하는 경우는 true.
                                              bool  pHistoryAdd)
{
  //[2007.11.16.화][생성!!!]{----------------------------------------------------------------------
  //현재 [입력지정자] 위치에 [CRLF] 를 끼워 넣어 행을 하나 추가한다.
  //[입력지정자] 는 다음행의 가장 처음에 위치해야 히고,
  //[CRLF] 가 추가된 행부터 [편집기] 영역의 보이는 행의 끝까지 전부
  //문자열을 다시 출력해 주어야 한다.
  //
  //[2007.02.13.화][추가!!!]-----------------------------------------------------------------------
  //[선택영역] 이 이미 존재하는 경우 별도 처리를 추가한다.
  //
  //[2007.02.14.수][수정!!!]-----------------------------------------------------------------------
  //[선택영역] 을 _SELECT_Delete() 함수로 삭제할때 [선택영역] 안에 CRLF 가 삭제되면
  //전체 행수가 줄어 들게 되므로 관리변수인 _linecount 를 여기서 직접 수정해 주어야 한다.
  //삭제된 CRLF 개수는 _SELECT_Delete() 함수에서 반환된다.
  //
  //[2007.02.27.화][수정!!!]-----------------------------------------------------------------------
  //먼저 삭제하기전에 [입력지정자] 를 [선택영역] 시작 위치로 이동하게 되는데,
  //이때 _EDIT_CaretPos() 함수안에서 [선택영역] 이 해제 되므로 정보를 상실하게 된다.
  //따라서, _SELECT_Get_StartEndIndex() 에서 얻어진 정보를 _EDIT_CaretPos() 함수 처리 후
  //다시 설정해 줌으로써 [선택영역] 을 _SELECT_Delete() 함수로 삭제할수 있게 만든다.
  //
  //[2007.03.11.일][수정!!!]-----------------------------------------------------------------------
  //caret_viewalways 를 사용하여 중복 처리를 막는다.
  //
  //[2007.03.26.월][수정!!!]-----------------------------------------------------------------------
  //[전체배경사용] 의 경우는 이 창의 위치에 해당하는 부분이 표시 되어야 한다.
  //
  //[2009.03.31.화][중요수정!!!]-------------------------------------------------------------------
  //BCB 와 같이 행을 변환하는 경우 이전 행의 처음 문자 위치에 [입력지정자] 가 위치하도록 수정한다.
  //이를 위하여 이전과 달리 다른 [키] 함수를 사용하지 않고 직접 처리하였다.
  //}----------------------------------------------------------------------------------------------

  //[방법]
  //{
      //-----------------------------------------------------------------------------------
      //(1) : _editbuf[] 상에 [CRLF] 를 집어 넣는다.
      //(2) : 문자열이 출력될 부분을 전부 지운다.
      //      단, 사각형 형태로 지워야 하므로 [CRLF] 가 추가된 행 시작부터 _bmp_ 의 끝까지
      //      영역 전부를 지운다. (CRLF 가 추가된 지점부터 지우지 않는다.)
      //(3) : _editbuf[] 상의 지정 범위의 문자열을 출력한다.
      //(4) : [입력지정자] 를 수정된 다음 행의 처음 위치로 이동시킨다.
      //      이는 _KEY_Home(), _KEY_Down() 함수의 동시 사용으로 간단하게 처리한다.
      //-----------------------------------------------------------------------------------
  //}

  //[주의!!!]
  //{
      //행이 바뀌므로 해당 정보를 전부 수정해 주어야 한다.
      //또한, 행이 수정되었으므로 직접 관련이 있는 [수직 스크롤] 정보도 같이 수정해 주어야 한다.
      //즉, [수직 스크롤] 을 다시 설정해 주어야 한다.

      //[2007.01.19.금][수정!!!]
      //이전에는 [편집기] 상의 보이는 영역 끝까지 지웠으나 이럴 경우 다음에 더 크게 크기를 조정하는경우
      //보이지 않던 영역이 나타나는 경우 이전 출력된 내용이 반영되지 않는 문제가 있다.
      //따라서, _bmp_ 의 끝까지 항상 지우는 것으로 수정한다.
  //}

  //[VAR]
  //{
      TRect             rect;
      int               i = 0;
      int               w, h;

      struct CARETINFO  select_start;
      struct CARETINFO  select_end;

      int               crlf_count = 0;

      //_CARET_ViewAlways() 함수가 내부적으로 동작한 경우 true 로 된다.
      bool              caret_viewalways = false;
      bool              select_use       = false;

      //[2009.03.31.화][추가!!!]
      int    spaceCount = 0;
      char   tempLineStr[OPT_lineStrSize*10];

      //[2012.06.11.월][추가!!!]
      //<_CommentBlock_Info()> 의 결과를 보관.
      bool   cmtBlkChanged = false;

  //}

  //[선택영역 처리]
  //{
      //[설명]{-----------------------------------------------
      //[2007.02.13.화]
      //1. 일단 [선택영역] 구간을 _editbuf[] 상에서 삭제한다.
      //2. 기본적인 <Enter-Key> 동작을 수행한다.
      //}-----------------------------------------------------

      //먼저 [입력지정자] 의 위치를 [선택영역] 시작 지점으로 이동시킨다.
      if(_SELECT_Get_StartEndIndex(&select_start, &select_end) != true) goto KEY_DEFAULT;


      if(pHistoryAdd == true)
      {
        //[수정이력][2009.05.03.일][추가!!!]{************************
        //[선택영역] 은 여기서 [삭제] 되므로 이를 기록한다.
        //[선택영역] 은 항상 관리 상태이므로 간단하게 처리 가능하다.
        //[수집 시작 위치]-------------------------------------------
        _history.strStartIndex = select_start.caret_index;
        //[수집 끝 위치]---------------------------------------------
        _history.strEndIndex   = select_end.caret_index;
        //[수집]-----------------------------------------------------
        //[삭제] 수정이다.
        History_Add('-', 's');
        //}**********************************************************

      }


      //[입력지정자 위치 수정]
      //{
          //[선택영역] 이 있는 경우만 처리한다.
          //[입력지정자] 위치는 select_startindex 위치가 된다.(작은 index)
          _caretindex = select_start.caret_index;
          _caret_x    = select_start.caret_x;
          _caret_y    = select_start.caret_y;

          //[입력지정자 위치 조정]
          _EDIT_CaretPos(_caret_x, _caret_y);

      //}

      //[입력지정자 항상 보이기]
      //{
          _editbuf_text_no = true;
          //{
              //키는 항상 눈에 보이는 위치에 있어야 한다.
              caret_viewalways = _CARET_ViewAlways(false);
              //<키> 를 처리하지 않고 여기서 종료 되므로 이곳에서 한번 실행해 주어야 한다.
          //}
          _editbuf_text_no = false;

      //}

      //[선택영역 정보 복구]
      //{
          //위에서 처리한 _EDIT_CaretPos() 에서 해제된 [선택영역] 의 정보를 다음 처리부에서
          //삭제할수 있도록 이미 얻어 놓은 정보로 복구한다.
          _select_start = select_start;
          _select_end   = select_end;

      //}

      //[선택영역] 삭제.
      if(_SELECT_Delete(&select_start, &crlf_count) == true)
      {
        //[선택영역] 을 처리했다는 것을 알린다.
        select_use = true;

        //[행수 수정]
        //{
            //CRLF 가 삭제된 것이 있는 경우만 수정한다.
            if(crlf_count > 0) { _linecount -= crlf_count; }

        //}

        //[삭제 반영]
        //{
            //<Enter-Key> 의 경우는 현재 행 부터 보이는 영역 끝까지 자동으로 다시 그려지므로
            //굳이 여기서 지금 수정 내용을 반영할 필요는 없다.
            //_EditBuf_Text();

        //}

        //[수직스크롤설정]
        //{
            //수정된 행이 있는 경우는 문서행수가 바뀌었으므로 [수직스크롤] 을
            //새로 설정해 주어야 한다.(여기서 종료하므로 이곳에서 처리한다)
            //이 키를 처리하면서 자동으로 처리되므로 여기서 처리하지 않는다.
            //if(crlf_count > 0) { _Scroll_Resize(); }

        //}

        //[묶음주석 정보 수집]
        //{
            //[2012.06.10.일][추가!!!]{---------------
            //반드시 [수정] 된 후에 [수집] 해야 한다.
            //}---------------------------------------

            //계속 이어지므로 여기서는 수집하지 않는다.
            //[2012.06.12.화][수정!!!]
            //부분정보 수집----------------------v
            //cmtBlkChanged = _CommentBlock_Info(true);

        //}

      }

      goto CONTINUE;

  //}

  //[순수한 KEY 처리]-----------------------------------------------------------

  KEY_DEFAULT:

  //[입력지정자 항상 보이기]
  //{
      _editbuf_text_no = true;
      //{
          //키는 항상 눈에 보이는 위치에 있어야 한다.
          caret_viewalways = _CARET_ViewAlways(false);
      //}
      _editbuf_text_no = false;

  //}

  CONTINUE:


  if(pHistoryAdd == true)
  {
    //[수정이력][2009.05.03.일][추가!!!]{**************************
    //[수집] 시작 위치를 기록한다.
    //[수집 시작 위치]---------------------------------------------
    _history.strStartIndex = _caretindex;
    //}************************************************************

  }


  //[버퍼 수정]
  //{
      //[새문장]
      //{
          //[2009.03.31.화][중요수정!!!]{---------------------------------------------
          //이전과 같이 단순하게 [행변환] 만 처리 하는 것이 아니라 BCB 처럼 이전 행의
          //시작 문자 위치에 [입력 지정자] 가 위치 할수 있도록 수정한다.
          //이는 보다 진보된 편집 기능으로 대단히 편리하고 유용한 기능이다.
          //금일, 큰마음 먹고 수정한다.현재 기능상 문제없이 잘 동작되고 있다.
          //}-------------------------------------------------------------------------

          //[추가 문자열 만들기]
          //{
              //[2009.05.09.토][중요추가!!!]{----------------------------------------
              //if(pHistoryAdd == true) 이 아닌 경우는 <i> 값이 0 으로 초기화 되지
              //않으므로 반드시 여기서 한번 초기화 해준다. 그렇지 않은 경우는 아래의
              //tempLineStr[2 + i] = '\0'; 부분에서 오류가 발생한다.
              i          = 0;
              spaceCount = 0;
              //}--------------------------------------------------------------------


              //일단 CRLF 를 추가한다.
              STR_Assign(tempLineStr, "\r\n");

              if(pHistoryAdd == true)
              {
                //[2009.05.09.토][중요수정!!!]{--------------------------------------------
                //이 함수는 [되돌림/되살림] 의 경우도 사용되는데 이때는 순수하게 <CRLF> 만
                //추가하기 위하여 사용되므로 이때는 [공백] 계산 처리를 하지 않아야 한다.
                //즉, 이 경우는 반드시 <pHistoryAdd:false> 가 되므로 걸러질수 있다.
                //}------------------------------------------------------------------------

                //지금 행의 선두부분의 [공백] 수를 구한다.
                spaceCount = STR_Get_ThisLinePreSpaceCount(_editbuf, _caretindex);

                //추가할 공백 만들기.
                for(i = 0; i < spaceCount; i++)
                {
                  //이미 CRLF 가 추가 된 상태이므로 이 다음 위치부터 기록해야 한다.
                  tempLineStr[2 + i] = ' ';

                }

              }


              //[문자열] 을 마무리 한다.
              tempLineStr[2 + i] = '\0';

          //}

          //[문자열] 추가
          _EditBuf_LineStr_Insert(_caretindex, tempLineStr);

      //}

      //[이전 문장]
      //{
          /*
          //_editbuf[] 상의 _caretindex 위치에 CRLF 를 집어 넣어 행을 추가한다.
          _EDITBUF_MOONJA_Insert(_caretindex, 0x0d0a);

          //[참고!!!][처리속도관련]
          //{
              //계속 [Enter-Key] 를 누르고 있는 경우 _KEY_Enter() 가 호출되는데,
              //_EDITBUF_MOONJA_Insert() 함수는 for() 문을 사용하여 일일히 _editbuf[] 의
              //내용을 밀어내기를 하므로 문서량이 많은 경우는 처리 속도가 느려질수 있다.
              //그러나, 10만줄의 경우도 그렇게 느낄 정도는 아니다.
          //}
          */

      //}

  //}


  if(pHistoryAdd == true)
  {
    //[수정이력][2009.05.03.일][추가!!!]{**********************************************
    //[저장소] 가 수정된 이후에야 [문자열] 을 수집 가능하다.
    //[수집 끝 위치]-------------------------------------------------------------------
    //<CRLF> 처리는 이전 행과 동기화를 위한 공백도 추가되므로 이것까지 반영하여
    //직접 길이를 구해서 처리해 주어야 한다.
    //이미 추가할 문자열이 <tempLineStr> 에 들어 있으므로 이 길이를 사용한다.
    _history.strEndIndex = _caretindex + STR_Length(tempLineStr);
    //[수집]---------------------------------------------------------------------------
    //[2009.05.09.토][중요수정!!!]
    //[공백] 이 추가된 경우는 <CRLF> 만 있는 경우가 아니므로 [문자열] 로 등록한다.
    //기본 적으로는 [추가] 수정이다.
    if(spaceCount == 0) { History_Add('+', 'c'); } //<CRLF> 만 추가된 경우.
    else                { History_Add('+', 's'); } //공백을 포함한 문자열 추가인 경우.
    //}********************************************************************************

  }

  //[묶음주석 정보 수집]
  //{
      //[2012.06.10.일][추가!!!]{---------------
      //반드시 [수정] 된 후에 [수집] 해야 한다.
      //}---------------------------------------

      //[2012.06.12.화][수정!!!]
      //부분정보 수집--------------------v
      cmtBlkChanged = _CommentBlock_Info(true);

  //}

  //[행수증가]
  //{
      //CRLF 가 추가되어 행이 하나 증가된 것이다.
      _linecount++;

  //}

  //[출력 위치 지우기]
  //{
      if((caret_viewalways == false) && (select_use == false))
      {
        //현재 [입력지정자] 가 위치한 행의 처음부터 _bmp_ 의 끝까지 전부 지운다.

        //[영역구하기]
        //{
            rect     = _bmp_->Canvas->ClipRect;
            rect.Top = _text_org_y + _caret_y;

        //}

        //[출력영역지우기]
        //{
            if(IDE_BACKBMP_entire)
            {
              //이 경우는 한개의 그림을 여러창에서 나누어 사용해야 한다.

              //[표시 시작 위치 계산]
              //{
                  //크기가 변경되는 경우는 전체 바탕그림을 표시하는 시작 위치도 변경된다.
                  //이는 마치 한개의 동일한 그림 위에 투명하게 위치하는 것같은 느낌을 주기 위한 것이다.
                  _bmporg_x = ide_editor_Form->Left - d_border_width + 1;
                  _bmporg_y = 0;

              //}

              //그냥 지우면 배경 그림이 지워지므로 반드시 배경 그림을 사용하여 지워야 한다.
              BitBlt(_bmp_->Canvas->Handle, rect.Left, rect.Top, _bmp_->Width,
                     //적용 영역의 높이는 현재 행부터 _bmp_ 끝까지 해당한다.
                     _bmp_->Height - (_text_org_y + _caret_y),
                     _bmp_back_->Canvas->Handle, _bmporg_x + rect.Left, _bmporg_y + rect.Top, SRCCOPY);

            }
            else
            {
              //그냥 지우면 배경 그림이 지워지므로 반드시 배경 그림을 사용하여 지워야 한다.
              BitBlt(_bmp_->Canvas->Handle, rect.Left + d_gutter_width, rect.Top, _bmp_->Width,
                     //적용 영역의 높이는 현재 행부터 _bmp_ 끝까지 해당한다.
                     _bmp_->Height - (_text_org_y + _caret_y),
                     _bmp_back_->Canvas->Handle, rect.Left, rect.Top, SRCCOPY);

            }

        //}

      }

  //}

  //[정지줄 처리]
  //{
      //[2007.04.16.월][추가!!!]{-------------------------------
      //현재 행 부터 보이는 영역끝까지 [정지줄] 을 만들어 준다.
      //}-------------------------------------------------------

      _BREAKPOINT_Edit_StartLine_Draw(_caret_y / _line_height);

  //}

  //[문자열]
  //{
      if((caret_viewalways == false) && (select_use == false))
      {
        //[수평스크롤 적용]
        //{
            //[!]{---------------------------------------------------------------------------
            //x 출력 위치는 기본적으로 margin_size 을 기준으로 출력된다.
            //실제 출력시 사용되는 함수상의 x 좌표는 margin_size 에 대한 offset 위치가 된다.
            //}------------------------------------------------------------------------------

            _font.margin_size = _text_org_x;

        //}

        //[현재행 시작 위치 구하기]
        //{
            //[2007.02.20.화][추가!!!]{----------------------------------------------------------
            //[선택영역]이 위에서 해제되는 경우 [입력지정자] 위치가 바뀌에 되어 _caretindex 값도
            //수정되므로 [입력지정자] 가 위치한 행의 시작 index 도 다시 계산해 주어야 한다.
            //}----------------------------------------------------------------------------------

            STR_Get_ThisLineStartIndex(_editbuf, _caretindex, &_linestartindex);

        //}

        //새로 적용하는 함수.
        _EDITBUF_STRING_Out(0, _text_org_y + _caret_y, _linestartindex);

      }

  //}

  //[검증창 반영]
  //{
      //[2007.04.09.월][추가!!!]
      //[검증창] 은 모든 내용이 다 그려진 다음에 가장 나중에 출력되어야 한다.
      //다른 내용 가장 위에 위치해야 하므로.
      BitBlt(_bmp_->Canvas->Handle, 0, rect.Top, d_gutter_width,
             //적용 영역의 높이는 현재 행부터 _bmp_ 끝까지 해당한다.
             _bmp_->Height - (_text_org_y + _caret_y),
             _bmp_debug->Canvas->Handle, 0, rect.Top, SRCCOPY);

  //}

  //[수직스크롤설정]
  //{
      //문서행수가 바뀌었으므로 [수직스크롤] 을 새로 설정해 주어야 한다.
      _Scroll_Resize();

  //}

  //[입력지정자 이동]
  //{
      //[!]{----------------------------------------------------------------------------
      //추가된 다음 행의 첫 위치로 이동해야 한다.
      //이는 두가지 키조합으로 간단하게 처리 가능하다.
      //단, _Scroll_Resize() 함수로 [수직스크롤] 이 완전히 수정된 이후에 처리해야 한다.
      //}-------------------------------------------------------------------------------

      //[입력지정자 위치 구하기]
      //{
          //[2009.03.31.화][중요수정!!!]{-------------------------------------------
          //이전 처럼 KEY_Home(), KEY_Down() 함수를 사용하지 않고 직접 구현한다.
          //수직 = 현재행위치 + 행길이.                     <---다음행으로 이동.
          //수평 = 현재 행 시작위치에서 공백을 추가한 위치. <---_caretindex 수정.
          //
          //[참고!!!]---------------------------------------------------------------
          //이미 선택영역은 위에서 모두 처리된 상태이므로 여기서는 신경쓰지 않는다.
          //}-----------------------------------------------------------------------

          //[<_caretindex> 수정]
          //{
              //<CRLF:2> + [공백개수:spaceCount] 로 수정되어야 한다.
              _caretindex += (2 + spaceCount);

          //}

          //[<_caret_x> 구하기]
          //{
              //이미 CRLF가 먼처 추가 되어 현재 _caretindex 위치는 행이 바뀐 위치 이므로 이를
              //반영하여 다시 지금 행의 처음 위치를 구한다.
              STR_Get_ThisLineStartIndex(_editbuf, _caretindex, &_linestartindex);

              //현재 <_caretindex> 위치로 [입력 지정자] x 위치를 구한다.
              _CARETINDEX_CaretIndexWidth(_linestartindex, _caretindex, &_caretindexwidth, &_col);
              _caret_x = _caretindexwidth;

          //}

          //[<_caret_y> 구하기]
          //{
              //다음행으로 이동한다.
              _caret_y += _line_height;

          //}

      //}

      //[입력 지정자 위치시키기]
      //{
          //[2009.03.31.화][중요수정!!!]
          //다른 조건 없이 무조건 실행 시켜야 한다.
          _EDIT_CaretPos(_caret_x, _caret_y);

          //[입력지정자 항상 보이기]{---------------------------------------------------
          //수정되는 부분이 보이지 않는 영역에 있는 경우는 보이는 영역으로 위치 시킨다.
          _editbuf_text_no = true;
          caret_viewalways = _CARET_ViewAlways(false);
          _editbuf_text_no = false;
          //}---------------------------------------------------------------------------

      //}

  //}

  //[수정된 영역만 다시 그리기]
  //{
      if((caret_viewalways == false) && (select_use == false)
         //[2012.06.11.월][추가!!!]
         //[묶음주석] 정보가 수정되지 않은 경우만 해당.
         //단, [KEY_Enter()] 의 경우는 항상 현재 행 아래를 전부 다시 그리기 때문에
         //굳이 전체를 다시 그릴 필요가 없으므로 주석으로 처리해 놓는다.
         //&& (cmtBlkChanged != true)
        )
      {
        //_Draw() 함수를 사용하여 전체를 다시 그리지 않고 수정된 행만 다시 그려준다.
        //이는 키가 계속눌려서 문자가 계속 출력되는 경우 처리속도를 최대한 높이기 위한 것이다.
        BitBlt(this->Canvas->Handle, rect.Left, rect.Top, this->Width,
               //적용 영역의 높이는 현재 행부터 _bmp_ 끝까지 해당한다.
               _bmp_->Height - (_text_org_y + _caret_y),
               _bmp_->Canvas->Handle, rect.Left, rect.Top, SRCCOPY);

      }
      else
      {
        _EditBuf_Text();

      }

  //}

  return;

}

void __fastcall Teditor_edit_Form::_KEY_Delete(//[수정이력] 을 적용하는 경우는 true.
                                               bool  pHistoryAdd)
{
  //[2007.01.18.목][생성!!!]{-------------------------------------------------------------
  //[Delete-Key] 를 누른 경우를 처리한다.
  //[일반문자] 의 경우와 [CRLF] 의 경우를 구분하여 처리해야 한다.

  //[2007.02.01.목][수정!!!]
  //이전에는 [입력지정자] 의 위치에서부터 행 끝가지 다시 출력했으나 [문법강조] 를 위하여
  //행의 처음부터 완전히 다시 출력하는 것으로 수정한다.

  //[2007.02.13.화][추가!!!]
  //[선택영역] 이 이미 존재하는 경우 별도 처리를 추가한다.

  //[2007.02.20.화][수정!!!]
  //[선택영역] 을 _SELECT_Delete() 함수로 삭제할때 [선택영역] 안에 CRLF 가 삭제되면
  //전체 행수가 줄어 들게 되므로 관리변수인 _linecount 를 여기서 직접 수정해 주어야 한다.
  //삭제된 CRLF 개수는 _SELECT_Delete() 함수에서 반환된다.

  //[2007.02.27.화][수정!!!]
  //먼저 삭제하기전에 [입력지정자] 를 [선택영역] 시작 위치로 이동하게 되는데,
  //이때 _EDIT_CaretPos() 함수안에서 [선택영역] 이 해제 되므로 정보를 상실하게 된다.
  //따라서, _SELECT_Get_StartEndIndex() 에서 얻어진 정보를 _EDIT_CaretPos() 함수 처리 후
  //다시 설정해 줌으로써 [선택영역] 을 _SELECT_Delete() 함수로 삭제할수 있게 만든다.

  //[2007.03.11.일][수정!!!]
  //caret_viewalways 를 사용하여 중복 처리를 막는다.

  //[2007.03.26.월][수정!!!]
  //[전체배경사용] 의 경우는 이 창에 해당하는 부분이 표시 되도록 한다.
  //}-------------------------------------------------------------------------------------

  //[주의!!!]{--------------------------------------------------------------------------------------
  //[2007.01.19.금][수정!!!]
  //이전에는 [편집기] 상의 보이는 영역 끝까지 지웠으나 이럴 경우 다음에 더 크게 크기를 조정하는경우
  //보이지 않던 영역이 나타나는 경우 이전 출력된 내용이 반영되지 않는 문제가 있다.
  //따라서, _bmp_ 의 끝까지 항상 지우는 것으로 수정한다.
  //
  //[2009.05.03.일][중요수정!!!---------------------------------------------------------------------
  //이 함수는 History_SelectDelete() 함수에서 [되돌리기/되살리기] 를 처리하는 경우에도
  //사용되므로 [되돌리기/되살리기] 를 다시 [수정이력] 으로 간주하지 않도록 [인수] 를 추가한다.
  //}-----------------------------------------------------------------------------------------------

  //[VAR]
  //{
      TRect             rect;
      int               i;
      int               w, h;

      //삭제된 문자가 [CRLF] 인지 구분 여부가 들어있다.
      bool              is_crlf = false;

      int               r_lineendindex;

      struct CARETINFO  select_start;
      struct CARETINFO  select_end;

      int               crlf_count = 0;

      //_CARET_ViewAlways() 함수가 내부적으로 동작한 경우 true 로 된다.
      bool              caret_viewalways = false;
      bool              select_use       = false;

      //[2012.06.11.월][추가!!!]
      //<_CommentBlock_Info()> 의 결과를 보관.
      bool   cmtBlkChanged = false;

  //}

  //[선택영역 처리]
  //{
      //[설명]{-----------------------------------------------
      //[2007.02.20.화]
      //1. 일단 [선택영역] 구간을 _editbuf[] 상에서 삭제한다.
      //2. <Key> 동작은 처리하지 않는다. (바로 종료한다.)
      //}-----------------------------------------------------

      //먼저 [입력지정자] 의 위치를 [선택영역] 시작 지점으로 이동시킨다.
      if(_SELECT_Get_StartEndIndex(&select_start, &select_end) != true) goto KEY_DEFAULT;


      if(pHistoryAdd == true)
      {
        //[수정이력][2009.05.03.일][추가!!!]{************************
        //[선택영역] 은 여기서 [삭제] 되므로 이를 기록한다.
        //[선택영역] 은 항상 관리 상태이므로 간단하게 처리 가능하다.
        //[수집 시작 위치]-------------------------------------------
        _history.strStartIndex = select_start.caret_index;
        //[수집 끝 위치]---------------------------------------------
        _history.strEndIndex   = select_end.caret_index;
        //[수집]-----------------------------------------------------
        //[삭제] 수정이다.
        History_Add('-', 's');
        //}**********************************************************

      }

      if(pHistoryAdd != true)
      {
        //[_EditBuf_Text() 기능 제어]{-----------------
        //[2009.05.07.목][추가!!!]
        //_EditBuf_Text() 함수가 동작되지 못하게 한다.
        _editBuf_Text_No_Select = true;
        //}--------------------------------------------

      }


      //[입력지정자 위치 수정]
      //{
          //[선택영역] 이 있는 경우만 처리한다.
          //[입력지정자] 위치는 select_startindex 위치가 된다.(작은 index)
          _caretindex = select_start.caret_index;
          _caret_x    = select_start.caret_x;
          _caret_y    = select_start.caret_y;

          //[입력지정자 위치 조정]
          _EDIT_CaretPos(_caret_x, _caret_y);

      //}


      if(pHistoryAdd != true)
      {
        //[_EditBuf_Text() 기능 제어]{------------
        //[2009.05.07.목][추가!!!]
        //_EditBuf_Text() 함수가 동작되게 만든다.
        _editBuf_Text_No_Select = false;
        //}---------------------------------------

      }

      //[입력지정자 항상 보이기]
      //{
          //_EditBuf_Text() 함수가 바로 다음에 실행되므로 아래 함수 처리시
          //동작하지 않게 만든다.
          _editbuf_text_no = true;
          //{
              //키는 항상 눈에 보이는 위치에 있어야 한다.
              _CARET_ViewAlways(false);
              //<키> 를 처리하지 않고 여기서 종료 되므로 이곳에서 한번 실행해 주어야 한다.
          //}
          _editbuf_text_no = false;

      //}

      //[선택영역 정보 복구]
      //{
          //위에서 처리한 _EDIT_CaretPos() 에서 해제된 [선택영역] 의 정보를 다음 처리부에서
          //삭제할수 있도록 이미 얻어 놓은 정보로 복구한다.
          _select_start = select_start;
          _select_end   = select_end;

      //}

      //[선택영역] 삭제.
      if(_SELECT_Delete(&select_start, &crlf_count) == true)
      {
        //[행수 수정]
        //{
            //CRLF 가 삭제된 것이 있는 경우만 수정한다.
            if(crlf_count > 0) { _linecount -= crlf_count; }

        //}

        //[묶음주석 정보 수집]
        //{
            //[2012.06.10.일][추가!!!]{----------------------------------
            //반드시 [수정] 된 후에 [다시 그리기] 전에 [수집] 해야 한다.
            //}----------------------------------------------------------

            //[2012.06.12.화][수정!!!]
            //부분정보 수집--------------------v
            cmtBlkChanged = _CommentBlock_Info(true);

        //}

        //[수정 반영]
        //{
            //[선택영역] 이 삭제된 경우는 <키> 를 처리하지 않고 여기서 종료하게
            //되므로 이곳에서 직접 수정된 내용을 반영해 주어야 한다.
            _EditBuf_Text();

        //}

        //[수직스크롤설정]
        //{
            //수정된 행이 있는 경우는 문서행수가 바뀌었으므로 [수직스크롤] 을
            //새로 설정해 주어야 한다.(여기서 종료하므로 이곳에서 처리한다)
            if(crlf_count > 0) { _Scroll_Resize(); }

        //}

        //<키> 처리를 하지 않고 여기서 종료한다.
        return;

      }

  //}

  //[순수한 KEY 처리]-----------------------------------------------------------

  KEY_DEFAULT:

  //[입력지정자 항상 보이기]
  //{
      _editbuf_text_no = true;
      //{
          //키는 항상 눈에 보이는 위치에 있어야 한다.
          caret_viewalways = _CARET_ViewAlways(false);
      //}
      _editbuf_text_no = false;
  //}


  if(pHistoryAdd == true)
  {
    //[수정이력][2009.05.03.일][추가!!!]{*********************************************
    ///한글/영문/CRLF 3가지 종류가 존재한다.
    //[수집 시작 위치]----------------------------------------------------------------
    _history.strStartIndex = _caretindex;
    //[수집 끝 위치]------------------------------------------------------------------
    //[한글/영문/CRLF] 을 구분하여 처리해야 한다.
    if     ((_editbuf[_caretindex] == 0x0d) && (_editbuf[_caretindex + 1] == 0x0a))
    {
      //<CRLF> 인 경우.
      _history.strEndIndex = _caretindex + 2;

    }
    else if(_editbuf[_caretindex] < 0)
    {
      //한글.
      _history.strEndIndex = _caretindex + 2;

    }
    else
    {
      //영문.
      _history.strEndIndex = _caretindex + 1;

    }
    //[수집]--------------------------------------------------------------------------
    //아직 대상이 [삭제] 되기 전에 처리해야 한다.
    //[삭제] 수정이다.
    History_Add('-', 'c');
    //}*******************************************************************************

  }


  //[문자 삭제]
  //{
      //_editbuf[] 상의 _caretindex 위치에 있는 문자를 한개 삭제한다.
      //문자가 삭제 되지 않은 경우는 처리하지 않는다.
      if(_EDITBUF_MOONJA_Delete(_caretindex, &is_crlf) != true) return;

  //}

  //[묶음주석 정보 수집]
  //{
      //[2012.06.10.일][추가!!!]{---------------
      //반드시 [수정] 된 후에 [수집] 해야 한다.
      //}---------------------------------------

      //[2012.06.12.화][수정!!!]
      //부분정보 수집--------------------v
      cmtBlkChanged = _CommentBlock_Info(true);

  //}

  //[행변환유무검사]
  //{
      if(is_crlf == true)
      {
        //[설명]{--------------------------------------------------------------------
        //이 경우는 CRLF 가 삭제되어 행수가 수정된 것이다.
        //따라서, 현재 행부터 보이는 [편집기] 끝까지 전부 새로 문서를 출력해야 한다.
        //단, [수직스크롤] 은 되지 않으나 문서행수가 줄어 들게 되므로 문서양에 맞게
        //[수직스크롤] 을 다시 설정해 주어야 한다.
        //}--------------------------------------------------------------------------

        //[행수수정]
        //{
            //CRLF 가 삭제되었으므로 행이 하나 줄었다.
            _linecount--;
        //}

        if(caret_viewalways == false)
        {
          //[출력 위치 지우기]
          //{
              //현재 [입력지정자] 가 위치한 행의 처음부터 _bmp_ 의 끝까지 [사각형] 영역을 완전히 지운다.

              //[영역구하기]
              //{
                  rect     = _bmp_->Canvas->ClipRect;
                  rect.Top = _text_org_y + _caret_y;

              //}

              //[출력영역지우기]
              //{
                  if(IDE_BACKBMP_entire)
                  {
                    //이 경우는 한개의 그림을 여러창에서 나누어 사용해야 한다.

                    //[표시 시작 위치 계산]
                    //{
                        //크기가 변경되는 경우는 전체 바탕그림을 표시하는 시작 위치도 변경된다.
                        //이는 마치 한개의 동일한 그림 위에 투명하게 위치하는 것같은 느낌을 주기 위한 것이다.
                        _bmporg_x = ide_editor_Form->Left - d_border_width + 1;

                        _bmporg_y = 0;

                    //}

                    //그냥 지우면 배경 그림이 지워지므로 반드시 배경 그림을 사용하여 지워야 한다.
                    BitBlt(_bmp_->Canvas->Handle, rect.Left, rect.Top, _bmp_->Width,
                           //적용 영역의 높이는 현재 행부터 _bmp_ 의 끝까지 해당한다.
                           _bmp_->Height - (_text_org_y + _caret_y),
                           _bmp_back_->Canvas->Handle, _bmporg_x + rect.Left, _bmporg_y + rect.Top, SRCCOPY);

                  }
                  else
                  {
                    //그냥 지우면 배경 그림이 지워지므로 반드시 배경 그림을 사용하여 지워야 한다.
                    BitBlt(_bmp_->Canvas->Handle, rect.Left + d_gutter_width, rect.Top, _bmp_->Width,
                           //적용 영역의 높이는 현재 행부터 _bmp_ 의 끝까지 해당한다.
                           _bmp_->Height - (_text_org_y + _caret_y),
                           _bmp_back_->Canvas->Handle, rect.Left, rect.Top, SRCCOPY);

                  }

              //}

          //}

          //[정지줄 처리]
          //{
              //[2007.04.16.월][추가!!!]
              //[편집기] 상에 현재 행부터 보이는 영역 끝까지 [정지줄] 을 만들어 준다.
              //아래 함수에서 자동적으로 보이는 영역에만 그려지게 된다.
              _BREAKPOINT_Edit_StartLine_Draw(_caret_y / _line_height);
              
          //}

          //[문자열]
          //{
              //[현재행 시작 위치 구하기]
              //{
                  //[2009.05.06.수][중요추가!!!]{-----------------------------------------------------
                  //[수정이력] 시에는 직접 [입력 지정자] 를 이동 시키게 되므로 <_linestartindex> 값이
                  //추적되고 있던 값이 아니게 된다. 따라서, 여기서 다시 구해준다.
                  //}---------------------------------------------------------------------------------

                  STR_Get_ThisLineStartIndex(_editbuf, _caretindex, &_linestartindex);

              //}

              //[수평스크롤 적용]
              //{
                  //x 출력 위치는 기본적으로 margin_size 을 기준으로 출력된다.
                  //실제 출력시 사용되는 함수상의 x 좌표는 margin_size 에 대한 offset 위치가 된다.
                  _font.margin_size = _text_org_x;

              //}

              //새로 적용하는 함수.
              _EDITBUF_STRING_Out(0, _text_org_y + _caret_y, _linestartindex);
          //}

          //[검증창 반영]
          //{
              //[2007.04.09.월][추가!!!]
              //[검증창] 은 모든 내용이 다 그려진 다음에 가장 나중에 출력되어야 한다.
              //다른 내용 가장 위에 위치해야 하므로.
              BitBlt(_bmp_->Canvas->Handle, rect.Left, rect.Top, d_gutter_width,
                     //적용 영역의 높이는 현재 행부터 _bmp_ 끝까지 해당한다.
                     _bmp_->Height - (_text_org_y + _caret_y),
                     _bmp_debug->Canvas->Handle, rect.Left, rect.Top, SRCCOPY);
          //}

        }

        //[수직스크롤설정]
        //{
            //문서행수가 바뀌었으므로 [수직스크롤] 을 새로 설정해 주어야 한다.
            _Scroll_Resize();
        //}

        //[입력지정자 이동]
        //{
            //현재 [입력지정자] 위치의 문자만 지우므로 위치는 그대로 있으면 된다.
        //}

        if((caret_viewalways == false)
           //[2012.06.11.월][추가!!!]
           //[묶음주석] 정보가 수정된 경우는 [전체 다시 그리기] 로 처리해야 한다.
           //<KEY_Enter()> 와 같은 경우로 현재 행에서 아래 끝 까지 전부다 [다시 그리기] 되므로
           //여기서는 처리 하지 않고 주석으로 둔다.
           //&& (cmtBlkChanged != true)
          )

        {
          //[수정된 영역만 다시 그리기]
          //{
              //_Draw() 함수를 사용하여 전체를 다시 그리지 않고 수정된 행만 다시 그려준다.
              //이는 키가 계속눌려서 문자가 계속 출력되는 경우 처리속도를 최대한 높이기 위한 것이다.
              BitBlt(this->Canvas->Handle, rect.Left, rect.Top, this->Width,
                     //적용 영역의 높이는 현재 행부터 _bmp_ 의 끝까지 해당한다.
                     _bmp_->Height - (_text_org_y + _caret_y),
                     _bmp_->Canvas->Handle, rect.Left, rect.Top, SRCCOPY);
          //}
        }
        else
        {
          _EditBuf_Text();

        }

      }
      else
      {
        //[설명]{-------------------------------------------------
        //이 경우는 일반 문자가 삭제된 것이므로 행의 변화는 없다.
        //따라서, 현재 행만 다시 출력하여 수정하면 된다.
        //}-------------------------------------------------------

        if(caret_viewalways == false)
        {
          //[출력 위치 지우기]
          //{
              //현재 [입력지정자] 가 위치한 행의 처음부터 보이는 행의 마지막 행까지
              //[사각형] 영역을 완전히 지운다.

              //[영역구하기]
              //{
                  rect      = _bmp_->Canvas->ClipRect;
                  rect.Left = _text_org_x;
                  rect.Top  = _text_org_y + _caret_y;
              //}

              //[출력영역지우기]
              //{
                  if(IDE_BACKBMP_entire)
                  {
                    //이 경우는 한개의 그림을 여러창에서 나누어 사용해야 한다.

                    //[표시 시작 위치 계산]
                    //{
                        //크기가 변경되는 경우는 전체 바탕그림을 표시하는 시작 위치도 변경된다.
                        //이는 마치 한개의 동일한 그림 위에 투명하게 위치하는 것같은 느낌을 주기 위한 것이다.
                        _bmporg_x = ide_editor_Form->Left - d_border_width + 1;

                        _bmporg_y = 0;
                    //}

                    //현재 [입력지정자] 가 위치한 행만 지운다.
                    //그냥 지우면 배경 그림이 지워지므로 반드시 배경 그림을 사용하여 지워야 한다.
                    BitBlt(_bmp_->Canvas->Handle, rect.Left, rect.Top, rect.Right - rect.Left, _line_height,
                           _bmp_back_->Canvas->Handle, _bmporg_x + rect.Left, _bmporg_y + rect.Top, SRCCOPY);

                  }
                  else
                  {
                    //현재 [입력지정자] 가 위치한 행만 지운다.
                    //그냥 지우면 배경 그림이 지워지므로 반드시 배경 그림을 사용하여 지워야 한다.
                    BitBlt(_bmp_->Canvas->Handle, rect.Left, rect.Top, rect.Right - rect.Left, _line_height,
                           _bmp_back_->Canvas->Handle, rect.Left - d_gutter_width, rect.Top, SRCCOPY);

                  }

              //}

          //}

          //[정지줄 처리]
          //{
              //[2007.04.16.월][추가!!!]
              //현재 행이 [정지점] 이 있는 행인 경우는 배경에 [정지줄] 을 만들어 준다.
              _BREAKPOINT_Edit_Verify_Draw(_caret_y / _line_height);
          //}

          //[문자열]
          //{
              //[현재행 시작 위치 구하기]
              //{
                  STR_Get_ThisLineStartIndex(_editbuf, _caretindex, &_linestartindex);
              //}

              //[수평스크롤 적용]
              //{
                  //x 출력 위치는 기본적으로 margin_size 을 기준으로 출력된다.
                  //실제 출력시 사용되는 함수상의 x 좌표는 margin_size 에 대한 offset 위치가 된다.
                  _font.margin_size = _text_org_x;
              //}

              //현재 [입력지정자] 가 위치한 행 시작부터 끝까지 해당 문자열을 다시 츨력한다.
              //행 처음부터 다시 출력해야 [문법강조] 를 수행할수 있다.
              //입력위치 x 의 _text_org_x 는 이미 _font.margin_size 에 적용된 상태이므로 따로 더할필요는 없다.
              _EDITBUF_LINE_Out(0, _text_org_y + _caret_y, _linestartindex, &r_lineendindex);
          //}

          //[검증창 반영]
          //{
              //[2007.04.09.월][추가!!!]
              //[검증창] 은 모든 내용이 다 그려진 다음에 가장 나중에 출력되어야 한다.
              //다른 내용 가장 위에 위치해야 하므로.
              BitBlt(_bmp_->Canvas->Handle, 0, rect.Top, d_gutter_width, _line_height + 1,
                     _bmp_debug->Canvas->Handle, 0, rect.Top, SRCCOPY);
          //}

        }

        //[수직스크롤설정]
        //{
            //문서행수가 바뀌었으므로 [수직스크롤] 을 새로 설정해 주어야 한다.
            _Scroll_Resize();
        //}

        //[입력지정자 이동]
        //{
            //현재 [입력지정자] 위치의 문자만 지우므로 위치는 그대로 있으면 된다.
        //}

        if((caret_viewalways == false) &&
           //[2012.06.11.월][추가!!!]
           //[묶음주석] 정보가 수정된 경우는 [전체 다시 그리기] 로 처리해야 한다.
           (cmtBlkChanged != true))
        {
          //[수정된 영역만 다시 그리기]
          //{
              //_Draw() 함수를 사용하여 전체를 다시 그리지 않고 수정된 행만 다시 그려준다.
              //이는 키가 계속눌려서 문자가 계속 출력되는 경우 처리속도를 최대한 높이기 위한 것이다.
              BitBlt(this->Canvas->Handle, rect.Left, rect.Top, rect.Right - rect.Left, _line_height + 1,
                     _bmp_->Canvas->Handle, rect.Left, rect.Top, SRCCOPY);
          //}
        }
        else
        {
          _EditBuf_Text();

        }

      }
  //}

  return;

}

void __fastcall Teditor_edit_Form::_KEY_Backspace(void)
{
  //[2007.01.19.금][생성!!!]{-------------------------------------------------------------
  //[Backspace-Key] 를 누른 경우를 처리한다.
  //[일반문자] 의 경우와 [CRLF] 의 경우를 구분하여 처리해야 한다.
  //단, 모든 것은 이미 만들어진 KEY_XXX() 함수의 조합으로 간단하게 처리할수 있다.
  //이 경우 [스크롤] 의 경우도 완전히 자동으로 처리된다.
  //예상외로 처리 속도가 빠르다.([입력지정자] 의 이동 모습이 눈에 띄지 않는다.)

  //[2007.02.13.화][추가!!!]
  //[선택영역] 이 이미 존재하는 경우 별도 처리를 추가한다.

  //[2007.02.20.화][수정!!!]
  //[선택영역] 을 _SELECT_Delete() 함수로 삭제할때 [선택영역] 안에 CRLF 가 삭제되면
  //전체 행수가 줄어 들게 되므로 관리변수인 _linecount 를 여기서 직접 수정해 주어야 한다.
  //삭제된 CRLF 개수는 _SELECT_Delete() 함수에서 반환된다.

  //[2007.02.27.화][수정!!!]
  //먼저 삭제하기전에 [입력지정자] 를 [선택영역] 시작 위치로 이동하게 되는데,
  //이때 _EDIT_CaretPos() 함수안에서 [선택영역] 이 해제 되므로 정보를 상실하게 된다.
  //따라서, _SELECT_Get_StartEndIndex() 에서 얻어진 정보를 _EDIT_CaretPos() 함수 처리 후
  //다시 설정해 줌으로써 [선택영역] 을 _SELECT_Delete() 함수로 삭제할수 있게 만든다.

  //[2007.03.11.일][수정!!!]
  //caret_viewalways 를 사용하여 중복 처리를 막는다.
  //}-------------------------------------------------------------------------------------

  //[VAR]
  //{
      struct CARETINFO  select_start;
      struct CARETINFO  select_end;

      int               crlf_count = 0;

      //_CARET_ViewAlways() 함수가 내부적으로 동작한 경우 true 로 된다.
      bool              caret_viewalways = false;

      //[2012.06.11.월][추가!!!]
      //<_CommentBlock_Info()> 의 결과를 보관.
      bool   cmtBlkChanged = false;

  //}

  //[선택영역 처리]
  //{
      //[선택영역] 을 삭제하는 경우는 _caretindex == 0 인 경우도 동작을
      //해야 하므로 여기서 처리한다.

      //[설명]{-----------------------------------------------
      //[2007.02.13.화]
      //1. 일단 [선택영역] 구간을 _editbuf[] 상에서 삭제한다.
      //2. <Key> 동작은 처리하지 않는다. (바로 종료한다.)
      //}-----------------------------------------------------

      //먼저 [입력지정자] 의 위치를 [선택영역] 시작 지점으로 이동시킨다.
      if(_SELECT_Get_StartEndIndex(&select_start, &select_end) != true) goto KEY_DEFAULT;


      //[수정이력][2009.05.03.일][추가!!!]{************************
      //[선택영역] 은 여기서 [삭제] 되므로 이를 기록한다.
      //[선택영역] 은 항상 관리 상태이므로 간단하게 처리 가능하다.
      //[수집 시작 위치]-------------------------------------------
      _history.strStartIndex = select_start.caret_index;
      //[수집 끝 위치]---------------------------------------------
      _history.strEndIndex   = select_end.caret_index;
      //[수집]-----------------------------------------------------
      //[삭제] 수정이다.
      History_Add('-', 's');
      //}**********************************************************


      //[입력지정자 위치 수정]
      //{
          //[선택영역] 이 있는 경우만 처리한다.
          //[입력지정자] 위치는 select_startindex 위치가 된다.(작은 index)
          _caretindex = select_start.caret_index;
          _caret_x    = select_start.caret_x;
          _caret_y    = select_start.caret_y;

          //[입력지정자 위치 조정]
          _EDIT_CaretPos(_caret_x, _caret_y);
      //}

      //[입력지정자 항상 보이기]
      //{
          _editbuf_text_no = true;
          //{
              //키는 항상 눈에 보이는 위치에 있어야 한다.
              _CARET_ViewAlways(false);
              //<키> 를 처리하지 않고 여기서 종료 되므로 이곳에서 한번 실행해 주어야 한다.
          //}
          _editbuf_text_no = false;
      //}

      //[선택영역 정보 복구]
      //{
          //위에서 처리한 _EDIT_CaretPos() 에서 해제된 [선택영역] 의 정보를 다음 처리부에서
          //삭제할수 있도록 이미 얻어 놓은 정보로 복구한다.
          _select_start = select_start;
          _select_end   = select_end;
      //}

      //[선택영역] 삭제.
      if(_SELECT_Delete(&select_start, &crlf_count) == true)
      {
        //[행수 수정]
        //{
            //CRLF 가 삭제된 것이 있는 경우만 수정한다.
            if(crlf_count > 0) { _linecount -= crlf_count; }
        //}

        //[묶음주석 정보 수집]
        //{
            //[2012.06.10.일][추가!!!]{---------------
            //반드시 [수정] 된 후에 [수집] 해야 한다.
            //}---------------------------------------

            //[2012.06.12.화][수정!!!]
            //부분정보 수집--------------------v
            cmtBlkChanged = _CommentBlock_Info(true);

        //}

        //[수정 반영]
        //{
            //[선택영역] 이 삭제된 경우는 <키> 를 처리하지 않고 여기서 종료하게
            //되므로 이곳에서 직접 수정된 내용을 반영해 주어야 한다.
            _EditBuf_Text();
        //}

        //[수직스크롤설정]
        //{
            //수정된 행이 있는 경우는 문서행수가 바뀌었으므로 [수직스크롤] 을
            //새로 설정해 주어야 한다.(여기서 종료하므로 이곳에서 처리한다)
            if(crlf_count > 0) { _Scroll_Resize(); }

        //}

        //<키> 처리를 하지 않고 여기서 종료한다.
        return;

      }

  //}

  //[순수한 KEY 처리]-----------------------------------------------------------

  KEY_DEFAULT:

  //[입력지정자 항상 보이기]
  //{
      _editbuf_text_no = true;
      //{
          //키는 항상 눈에 보이는 위치에 있어야 한다.
          caret_viewalways = _CARET_ViewAlways(false);
      //}
      _editbuf_text_no = false;
  //}

  if(_caretindex <= 0)
  {
    //문서의 가장 처음 위치에 있는 경우는 더이상 처리할수 없다.
    //바로 종료한다.
    goto END;

  }

  if((_editbuf[_caretindex - 2] == 0x0d) && (_editbuf[_caretindex - 1] == 0x0a))
  {
    //현재 [입력지정자] 왼쪽의 문자가 CRLF 인경우.
    //CRLF 가 삭제되었으므로 윗행 마지막으로 이동해야 한다.

    //[이전안]{-----------------------------
    //_KEY_Up(false);
    //_KEY_End(false);
    //[수정안]------------------------------
    //[입력지정자] 위치 지정.
    _caretindex -= 2;
    History_SetCaretPos(_caretindex, true);
    //깜박거림 없이 깨끗하게 처리된다.
    //}-------------------------------------

    //_KEY_Delete() 내부에서 [수정이력] 이 자동 추가 되므로 여기서는 처리하지 않는다.
    /*
    //[수정이력][2009.05.03.일][추가!!!]{************************
    //<CRLF> 를 [삭제] 하는 경우다.
    //[수집 시작 위치]-------------------------------------------
    _history.strStartIndex = _caretindex;
    //[수집 끝 위치]---------------------------------------------
    //<CRLF> 2Byte 가 [삭제] 하므로 간단하게 위치를 구할수 있다.
    _history.strEndIndex = _caretindex + 2;
    //[수집]-----------------------------------------------------
    //아직 대상이 [삭제] 되기 전에 처리해야 한다.
    //[삭제] 수정이다.
    History_Add('-', 'c');
    //}**********************************************************
    */

    _KEY_Delete(true);

  }
  else
  {

    //현재 [입력지정자] 왼쪽의 문자가 [한글/영문] 인경우.
    //왼쪽의 문자를 삭제하면서 왼쪽으로 이동한다.
    _KEY_Left(false);
    //이것은 [한/영] 구분을 해야 하고 이 함수 자체가 처리가 복잡하지 않으므로
    //History_SetCaretPos(); 르르 사용하지 않고 그대로 위 함수를 사용하여 처리한다.


    //_KEY_Delete() 내부에서 [수정이력] 이 자동 추가 되므로 여기서는 처리하지 않는다.
    /*
    //[수정이력][2009.05.03.일][추가!!!]{*********************************************
    //[한글/영문] 한개 문자를 [삭제] 하는 경우다.
    //[수집 시작 위치]----------------------------------------------------------------
    _history.strStartIndex = _caretindex;
    //[수집 끝 위치]------------------------------------------------------------------
    //[한글/영문] 을 구분하여 처리해야 한다.
    if(_editbuf[_caretindex] < 0) { _history.strEndIndex = _caretindex + 2; } //한글.
    else                          { _history.strEndIndex = _caretindex + 1; } //영문.
    //[수집]--------------------------------------------------------------------------
    //아직 대상이 [삭제] 되기 전에 처리해야 한다.
    //[삭제] 수정이다.
    History_Add('-', 'c');
    //}*******************************************************************************
    */

    _KEY_Delete(true);

  }

  END:

  if(caret_viewalways == true)
  {
    _EditBuf_Text();

  }

  return;

}

bool __fastcall Teditor_edit_Form::_EDITBUF_MOONJA_Delete(int   pDELETEindex,
                                                          bool *rIScrlf)
{
  //[2007.01.18.목][생성!!!]{----------------------------------------------------
  //_editbuf[] 상의 지정 위치의 문자를 삭제한다.
  //memmove() 함수를 사용하여 고속으로 다음 문자열을 해당 문자위치에 당겨서 덮는
  //방식을 사용한다.
  //
  //[2012.05.24.목][수정!!!]-----------------------------------------------------
  //[2012.06.01.금][수정!!!]-----------------------------------------------------
  //}----------------------------------------------------------------------------

  //[주의!!!]
  //{
      //--------------------------------------------------------------------------------------
      //_filesize 는 FILE_Open_inBUF() 함수로 구해지므로 '\0' 을 포함한 크기다.
      //단, 문서가 수정된 것이므로 해당 정보도 다 수정해 주어야한다.

      //한글은 첫 byte 만 [음수] 가 아니라 2byte 각각 모두 음수이다.
      //이점을 주의해야 한다.
      //단, '똠' 과 같은 문자가 입력되는 경우는 자동으로 OS 가 [조합형코드] 로
      //바꾸어서 전달하는데 이 [조함형코드] 는 무조건 찻 byte 가 [음수] 이다.
      //따라서 [한글/영문] 을 구분하기 위해서는 반드시 첫 byte 가 [음수] 인지 확인해야 한다.
      //이는 순서대로 처리할때는 문제가 없으나, 역방향으로 버퍼를 거꾸로 검사하는 경우는
      //반드시 첫 byte 가 [음수] 인지 확인해 보아야 한다.

      //CRLF 가 처리되는 경우도 있으므로 이를 처리해 주어야 하는데,
      //0x0d0a 로 첫 byte 의 [음수] 인지 여부 만으로는 [영문] 으로 인식될수 있으므로
      //CRLF 는 별도로 검사해주어야 한다.

      //CRLF 를 삭제한 경우는 이를 알려 주어야 한다.(행이 바뀐 경우이므로 특별한 처리를 요함)
      //--------------------------------------------------------------------------------------
  //}

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

  //}

//[2012.05.31.목][임시문장]
//msg_msg_Form->_PrintAddLine(0, "_EDITBUF_MOONJA_Delete");

  //[한글/영문 인가?]
  //{
      if     (_editbuf[pDELETEindex] == '\0')
      {
        //현재 위치가 문서 끝이라면 더이상 처리하지 않는다.
        return(false);

      }
      else if((_editbuf[pDELETEindex] == 0x0d) && (_editbuf[pDELETEindex + 1] == 0x0a))
      {
        //CRLF.
        length     = 2;
        (*rIScrlf) = true;

      }
      else if(_editbuf[pDELETEindex] < 0)
      {
        //한글.
        length     = 2;
        (*rIScrlf) = false;

      }
      else
      {
        //영문.
        length     = 1;
        (*rIScrlf) = false;

      }
  //}

  //[정보수정]
  //{
      if(_filesize >= length)
      {
        //[공간 만들기]
        //{
            //당겨 붙이는 방법은 memmove() 함수를 사용하여 고속으로 간단하게 처리할수 있다.
            memmove(&(_editbuf[pDELETEindex]), &(_editbuf[pDELETEindex + length]),
                    //pDELETEindex 위치부터 파일끝까지만 당겨 붙이면 된다.
                    _filesize - pDELETEindex);
        //}

        //삭제한 문자의 길이만큼 [문서양] 이 준다.
        _filesize -= length;

      }
      else
      {
        //더이상 처리할수 없으므로 종료.
        return(false);

      }

  //}
  
  //[실시간 선언 정보판 관련]
  //{
      //[단어 구간 정보 추출]
      //{
          //[2012.05.24.목][추가!!!]{---------------------------------------------
          //실시간으로 [입력지정자] 가 위치한 [단어] 의 [시작/끝:위치] 를 관리.
          //
          //[2012.06.01.금][설명!!!]----------------------------------------------
          //<_EDITBUF_LINE_Out()> 에서 [실시간 선언 정보판:대상단어] 를 지정할때
          //<_wordStartIndex/_wordEndIndex> 정보를 사용하므로 항상 수집해 놓는다.
          //}---------------------------------------------------------------------

          STR_Get_WordBound(_editbuf, _filesize, _caretindex,
                            &_wordStartIndex,
                            &_wordEndIndex);

      //}

      //[실시간 선언 정보판 감추기]
      //{
          //[2012.05.24.목][추가!!!]{----------------------------
          //[실시간 선언 정보판] 이 보이는 경우만 처리하고
          //처리후 반드시 [단어지정] 을 위하여 [입력지정자] 가
          //위치한행만 다시 그린다.
          //
          //더불어, <info_tree_Form->_AutoHide_WordBound()> 에서
          //기존 [단어 구간] 을 벗어난 경우는 자동으로 감춰진다.
          //}----------------------------------------------------

          if(info_tree_Form != NULL)
          {
            if((info_tree_Form->Visible == true) &&
               //[2012.06.01.금][추가!!!]
               //<_AutoHide_WordBound()> 함수 사용 허가상태만 처리.
               (info_tree_Form->_sw_AutoHide_WordBound == true))
            {
              //현재 [단어 구간 정보] 전달.
              info_tree_Form->_AutoHide_WordBound(_wordStartIndex, _wordEndIndex);

              //현재 [입력지정자] 가 위치한 행만 다시 그린다.
              _EditBuf_LineText(_row, false);

            }

          }

      //}
      
  //}    

  return(true);

}

bool __fastcall Teditor_edit_Form::_SELECT_Get_StartEndIndex(struct CARETINFO  *rSELECTstart,
                                                             struct CARETINFO  *rSELECTend)
{
  //[2007.02.14.수][생성!!!]{------------------------------------------------------------------------------
  //현재 [선택영역] 졍보 _select_start.caret_index, _select_end.caret_index 의 값중 작은 값을
  //startindex 로, 큰 값을 endindex 로 구하여 반환한다.
  //이는 [선택영역] 을 아래에서 위로 설정하는 경우는 "_select_start.caret_index > _select_end.caret_index"
  //가 될수 있기 때문인데 무조건 "startindex < endindex" 를 만족시키는 값을 얻어야 한다.
  //[선택영역] 이 있어서 처리된 경우는 true 를 반환한다.

  //[2007.02.17.토][수정!!!]
  //struct CARETINFO 를 사용하여 정보 구조체를 전부 반환하는 것으로 수정한다.
  //}------------------------------------------------------------------------------------------------------

  //[선택영역 정리]
  //{
      if((_select_start.caret_index >= 0) &&
         (_select_end.caret_index >= 0)   &&
         //[2009.05.06.수][중요수정!!!]
         //선택값이 있더라도 두 값이 같은 경우는 [선택영역] 은 존재하지 않는 것이다.
         (_select_start.caret_index != _select_end.caret_index))

      {
        //[선택영역] 의 2 개 정보를 크기 순서로 다시 정리한다.
        //이는 [선택영역] 이 아래에서 위로 만들어 질수도 있기 때문이다.

        if(_select_start.caret_index <= _select_end.caret_index)
        {
          //[위=>아래] 로 기본적인 상태.
          (*rSELECTstart) = _select_start;
          (*rSELECTend)   = _select_end;
          return(true);

        }
        else
        {
          //[아래 => 위] 로 거꾸로 형성된 상태.
          (*rSELECTend)   = _select_start;
          (*rSELECTstart) = _select_end;
          return(true);

        }

      }
      else
      {
        //해당 없는 경우는 완전히 초기화 한다.
        rSELECTstart->caret_index = -1;
        rSELECTstart->caret_x     = 0;
        rSELECTstart->caret_y     = 0;

        rSELECTend->caret_index   = -1;
        rSELECTend->caret_x       = 0;
        rSELECTend->caret_y       = 0;

        return(false);

      }
  //}

  return(true) ;

}

bool __fastcall Teditor_edit_Form::_SELECT_Delete(struct CARETINFO  *rSELECTstart,
                                                  int               *rCRLFcount)
{
  //[2007.02.13.화][생성!!!]{---------------------------------------------------------------------
  //[선택영역] 의 문자열을 _editbuf[] 에서 삭제한다.
  //[선택영역] 정보는 관리변수 _select_start.caret_index, _select_endindex 를 참고한다.
  //[삭제] 하는 것은 memmove() 함수를 사용하여 고속으로 처리할수 있다.

  //_EDITBUF_MOONJA_Delete() 함수를 참고하여 만들었다.
  //_filesize 는 FILE_Open_inBUF() 함수로 구해지므로 '\0' 을 포함한 크기다.
  //단, 문서가 수정된 것이므로 해당 정보도 다 수정해 주어야한다.

  //[주의!!!][2007.02.14.수][수정!!!]
  //[선택영역] 안에 CRLF 가 들어 있는 개수만큼 행이 줄어 들게 되므로 이 함수를
  //사용하는 함수에서 관리정보인 _linecount 를 수정할수 있게 삭제된 구간안의
  //CRLF 의 개수를 반환한다.(전문 처리 함수를 사용한다.)

  //[2007.02.20.화][추가!!!]
  //여기서 [선택영역] 이 삭제 됬으므로 _select_start, _select_end 정보를 완전히 초기화 해야 한다.
  //
  //[2012.05.24.목][수정!!!]----------------------------------------------------------------------
  //[2012.06.01.금][수정!!!]----------------------------------------------------------------------
  //}---------------------------------------------------------------------------------------------

  //[VAR]
  //{
      int               i;

      int               del_length;
      int               move_length;

      struct CARETINFO  select_start;
      struct CARETINFO  select_end;

  //}

//[2012.05.31.목][임시문장]
//msg_msg_Form->_PrintAddLine(0, "_SELECT_Delete");

  //[선택영역 정보 얻기]
  //{
      //처리할 [선택영역] 이 없는 경우는 여기서 바로 종료한다.
      if(_SELECT_Get_StartEndIndex(&select_start, &select_end) != true) return(false);

      //현재 [선택영역] 의 index 중 작은 값을 반환한다.
      (*rSELECTstart) = select_start;

      //삭제된 CRLF 개수 구하기.
      (*rCRLFcount) = STR_Get_CRLF_Count_withStartEndIndex(_editbuf, select_start.caret_index, select_end.caret_index);
  //}

  //[길이 정보 구하기]
  //{
      //삭제되는 [선택영역] 길이.
      del_length  = select_end.caret_index - select_start.caret_index;

      //복사 이동할 byte 단위 길이를 구한다.
      move_length = _filesize - select_end.caret_index;
  //}

  //[삭제]
  //{
      if(_filesize >= del_length)
      {
        //[공간 만들기]
        //{
            //memmove() 함수를 사용하여 _select_endindex => _select_start.caret_index 로
            //전부다 끌어당겨 붙이면 된다.
            memmove(&(_editbuf[select_start.caret_index]), &(_editbuf[select_end.caret_index]), move_length);
        //}

        //삭제한 문자의 길이만큼 [문서양] 이 준다.
        _filesize -= del_length;

      }
      else
      {
        //더이상 처리할수 없으므로 종료.
        return(false);

      }
  //}

  //[선택영역 초기화]
  //{
      //[2007.02.20.화][추가!!!]
      //[선택영역] 이 삭제 되었으므로 해당 정보를 완전히 초기화 한다.
      _Select_CaretIndex(&_select_start, -1); //_select_start.caret_index = -1;
      _select_start.caret_x     = 0;
      _select_start.caret_y     = 0;

      _Select_CaretIndex(&_select_end, -1); //_select_end.caret_index   = -1;
      _select_end.caret_x       = 0;
      _select_end.caret_y       = 0;

  //}

  //[실시간 선언 정보판 관련]
  //{
      //[단어 구간 정보 추출]
      //{
          //[2012.05.24.목][추가!!!]{---------------------------------------------
          //실시간으로 [입력지정자] 가 위치한 [단어] 의 [시작/끝:위치] 를 관리.
          //
          //[2012.06.01.금][설명!!!]----------------------------------------------
          //<_EDITBUF_LINE_Out()> 에서 [실시간 선언 정보판:대상단어] 를 지정할때
          //<_wordStartIndex/_wordEndIndex> 정보를 사용하므로 항상 수집해 놓는다.
          //}---------------------------------------------------------------------

          STR_Get_WordBound(_editbuf, _filesize, _caretindex,
                            &_wordStartIndex,
                            &_wordEndIndex);

      //}

      //[실시간 선언 정보판 감추기]
      //{
          //[2012.05.24.목][추가!!!]{----------------------------
          //[실시간 선언 정보판] 이 보이는 경우만 처리하고
          //처리후 반드시 [단어지정] 을 위하여 [입력지정자] 가
          //위치한행만 다시 그린다.
          //
          //더불어, <info_tree_Form->_AutoHide_WordBound()> 에서
          //기존 [단어 구간] 을 벗어난 경우는 자동으로 감춰진다.
          //}----------------------------------------------------

          if(info_tree_Form != NULL)
          {
            if((info_tree_Form->Visible == true) &&
               //[2012.06.01.금][추가!!!]
               //<_AutoHide_WordBound()> 함수 사용 허가상태만 처리.
               (info_tree_Form->_sw_AutoHide_WordBound == true))
            {
              //현재 [단어 구간 정보] 전달.
              info_tree_Form->_AutoHide_WordBound(_wordStartIndex, _wordEndIndex);

              //현재 [입력지정자] 가 위치한 행만 다시 그린다.
              _EditBuf_LineText(_row, false);

            }

          }

      //}
      
  //}    

  return(true);

}

int __fastcall Teditor_edit_Form::_SELECT_StartLineNum(void)
{
  //[2011.06.21.화][생성!!!]{---------------------------------------------------
  //현재 [편집기] 상의 선택영역의 첫행번호를 추출하여 반환한다.
  //이미 [선택영역정보] 는 관리되고 있으며, 반드시 보다 낮은 행이 [시작위치] 로
  //정리돼 있으므로 [시작위치] 정보를 바탕으로 간단하게 계산할수 있다.
  //
  //[2011.06.24.금][수정!!!]----------------------------------------------------
  //[시작/끝] 위치를 정리한뒤 항상 보다 작은 행을 시작행으로 간주한다.
  //}---------------------------------------------------------------------------

  //[VAR]
  //{
      //[2011.06.24.금][추가!!!]
      struct CARETINFO  select_start;
      struct CARETINFO  select_end;

  //}

  //[선택 영역 정보 얻기]
  //{
      //[2011.06.24.금][추가!!!]{-----------------------
      //[선택영역] 의 [시작/끝] 위치를 정리하여 얻는다.
      //단, [선택영역] 이 없는 경우는 <-1> 로 처리한다.
      //}-----------------------------------------------

      if(_SELECT_Get_StartEndIndex(&select_start, &select_end) != true) return(-1);

  //}

  return(select_start.caret_y / _line_height);

}

void __fastcall Teditor_edit_Form::_EDITBUF_MOONJA_Insert(int    pINSERTindex,
                                                          short  pCODE)
{
  //[2007.01.10.수][생성!!!]{--------------------------------------------------
  //_editbuf[] 상의 지정 위치에 전달받은 [문자코드] 의 문자를 끼워넣는다.
  //끼워 넣을 장소를 만드는데 처리의 특성상 memmove() 함수를 사용할수 없으므로
  //for() 문으로 직접 처리한다.
  //일단, 끼워넣을 문자 만큼의 공간을 만들고 해당 위치에 끼워넣으면 된다.
  //문자 한개만 처리하므로 [한글/영문] 인지만 구분하여 처리하면 된다.
  //
  //[2012.05.24.목][수정!!!]---------------------------------------------------
  //[2012.06.01.금][수정!!!]---------------------------------------------------
  //}--------------------------------------------------------------------------

  //[주의!!!]
  //{
      //------------------------------------------------------------------------
      //_filesize 는 FILE_Open_inBUF() 함수로 구해지므로 '\0' 을 포함한 크기다.
      //단, 문서가 수정된 것이므로 해당 정보도 다 수정해 주어야한다.
      //------------------------------------------------------------------------
  //}

  //[주의!!!][2007.01.14.일]
  //{
      //-------------------------------------------------------------------------------------
      //한글은 첫 byte 만 [음수] 가 아니라 2byte 각각 모두 음수이다.
      //이점을 주의해야 한다.
      //단, '똠' 과 같은 문자가 입력되는 경우는 자동으로 OS 가 [조합형코드] 로
      //바꾸어서 전달하는데 이 [조함형코드] 는 무조건 찻 byte 가 [음수] 이다.
      //따라서 [한글/영문] 을 구분하기 위해서는 반드시 첫 byte 가 [음수] 인지 확인해야 한다.
      //이는 순서대로 처리할때는 문제가 없으나, 역방향으로 버퍼를 거꾸로 검사하는 경우는
      //반드시 첫 byte 가 [음수] 인지 확인해 보아야 한다.
      //-------------------------------------------------------------------------------------
  //}

  //[수정!!!][2007.01.16.화]
  //{
      //CRLF 가 처리되는 경우도 있으므로 이를 처리해 주어야 하는데,
      //어차피 2 byte 라서 [한글] 처럼 검사되므로 추가 처리는 하지 않아도 자동으로 처리된다.
  //}

  //[참고!!!][2007.01.17.수]
  //{
      //계속 [Enter-Key] 를 누르고 있는 경우 _KEY_Enter() 가 호출되는데,
      //_EDITBUF_MOONJA_Insert() 함수는 for() 문을 사용하여 일일히 _editbuf[] 의
      //내용을 밀어내기를 하므로 문서량이 많은 경우는 처리 속도가 느려질수 있다.
      //그러나, 10만줄의 경우도 그렇게 느낄 정도는 아니다.
  //}

  //[VAR]
  //{
      int  i;

      //전달받은 문자열의 길이.
      int  length;
  //}

  //[한글/영문 인가?]
  //{
      if((pCODE & 0xff00) == 0)
      {
        //영문.
        length = 1;

      }
      else
      {
        //한글 또는 [CRLF] 가 된다.
        length = 2;

      }

  //}

//[2012.05.31.목][임시문장]
//msg_msg_Form->_PrintAddLine(0, "_EDITBUF_MOONJA_Insert");

  //[공간 만들기]
  //{
      //[2007.04.09.월][수정!!!]
      //for() 문을 사용하여 공간을 만드는 것은 문서량이 많은 경우 시간이 많이 걸리므로
      //_tempbuf[] 와 memmove() 함수를 사용하여 복사 방식으로 처리한다.

      //끼워 넣을 시작위치부터 문서끝까지의 문자열을 _tempbuf[] 에 대피시킨다.
      memmove(_tempbuf, &(_editbuf[pINSERTindex]), _filesize - pINSERTindex);

      //끼워넣을 공간 다음에 다시 복사해서 붙여준다.
      memmove(&(_editbuf[pINSERTindex + length]), _tempbuf, _filesize - pINSERTindex);

      /*
      //밀어내기의 경우는 memmove() 를 사용할수 없으므로 for() 문으로 일일히 복사하는 방법을 사용한다.
      for(i = _filesize; i >= pINSERTindex; i--)
      {
        //집어 넣을 문자열의 길이 만큼 공간을 만들어야 하므로 문자열의 길이만큼의 거리에 복사한다.
        _editbuf[i + length] = _editbuf[i];

      }
      */
  //}

  //[끼워넣기]
  //{
      //지정 위치에 문자열을 끼워넣는다.
      if(length == 1)
      {
        //영문.
        _editbuf[pINSERTindex] = (pCODE & 0xff);

      }                                      
      else
      {
        //한글.
        _editbuf[pINSERTindex + 0] = ((pCODE >> 8) & 0xff); //상위 바이트 출력.
        _editbuf[pINSERTindex + 1] = (pCODE & 0xff);        //하위 바이트 출력.

      }
  //}

  //[정보수정]
  //{
      //추가한 문자의 길이만큼 [문서양] 이 는다.
      _filesize += length;
      
  //}
  
  //[실시간 선언 정보판 관련]
  //{
      //[단어 구간 정보 추출]
      //{
          //[2012.05.24.목][추가!!!]{---------------------------------------------
          //실시간으로 [입력지정자] 가 위치한 [단어] 의 [시작/끝:위치] 를 관리.
          //
          //[2012.06.01.금][설명!!!]----------------------------------------------
          //<_EDITBUF_LINE_Out()> 에서 [실시간 선언 정보판:대상단어] 를 지정할때
          //<_wordStartIndex/_wordEndIndex> 정보를 사용하므로 항상 수집해 놓는다.
          //}---------------------------------------------------------------------

          STR_Get_WordBound(_editbuf, _filesize, _caretindex,
                            &_wordStartIndex,
                            &_wordEndIndex);

      //}

      //[실시간 선언 정보판 감추기]
      //{
          //[2012.05.24.목][추가!!!]{----------------------------
          //[실시간 선언 정보판] 이 보이는 경우만 처리하고
          //처리후 반드시 [단어지정] 을 위하여 [입력지정자] 가
          //위치한행만 다시 그린다.
          //
          //더불어, <info_tree_Form->_AutoHide_WordBound()> 에서
          //기존 [단어 구간] 을 벗어난 경우는 자동으로 감춰진다.
          //}----------------------------------------------------

          if(info_tree_Form != NULL)
          {
            if((info_tree_Form->Visible == true) &&
               //[2012.06.01.금][추가!!!]
               //<_AutoHide_WordBound()> 함수 사용 허가상태만 처리.
               (info_tree_Form->_sw_AutoHide_WordBound == true))
            {
              //현재 [단어 구간 정보] 전달.
              info_tree_Form->_AutoHide_WordBound(_wordStartIndex, _wordEndIndex);

              //현재 [입력지정자] 가 위치한 행만 다시 그린다.
              _EditBuf_LineText(_row, false);

            }

          }

      //}
      
  //}    

}

void __fastcall Teditor_edit_Form::_EditBuf_LineStr_Insert(int    pInsertIndex,
                                                           char  *pStr)
{
  //[2009.03.31.화][생성!!!]{------------------------------------------------------
  //현재 [저장소] 상의 위치에 [문자열] 을 끼워 넣는다.
  //_EDITBUF_MOONJA_Insert() 함수와 용도는 같으나 [문자] 가 아니라 [문자열] 을
  //처리하는 것만 다르다.
  //
  //[주의!!!]----------------------------------------------------------------------
  //이 함수는 <_caretindex> 를 수정하지 않으며 문자열에 CRLF 가 존재해서는 안된다.
  //
  //[2012.05.24.목][수정!!!]-------------------------------------------------------
  //[2012.06.01.금][수정!!!]-------------------------------------------------------
  //}------------------------------------------------------------------------------

  //[VAR]
  //{
      int  i;

      //전달받은 문자열의 길이.
      int  size;

  //}

//[2012.05.31.목][임시문장]
//msg_msg_Form->_PrintAddLine(0, "_EditBuf_LineStr_Insert");

  //[문자열 크기 얻기]
  //{
      size = strlen(pStr);

  //}

  //[공간 만들기]
  //{
      //[!]{---------------------------------------------------------------------------
      //for() 문을 사용하여 공간을 만드는 것은 문서량이 많은 경우 시간이 많이 걸리므로
      //_tempbuf[] 와 memmove() 함수를 사용하여 복사 방식으로 처리한다.
      //}------------------------------------------------------------------------------

      //끼워 넣을 시작위치부터 문서끝까지의 문자열을 _tempbuf[] 에 대피시킨다.
      memmove(_tempbuf, &(_editbuf[pInsertIndex]), _filesize - pInsertIndex);

      //끼워넣을 공간 다음에 다시 복사해서 붙여준다.
      memmove(&(_editbuf[pInsertIndex + size]), _tempbuf, _filesize - pInsertIndex);

  //}

  //[끼워넣기]
  //{
      //[!]{-----------------------------------------
      //비워진 공간에 전달받은 문자열을 끼워 넣는다.
      //memmove() 를 사용하여 고속으로 [복사] 한다.
      //}--------------------------------------------

      memmove(&(_editbuf[pInsertIndex]), pStr, size);

  //}

  //[문서량수정]
  //{
      //추가한 문자열 길이만큼 [문서량] 을 수정한다.
      _filesize += size;

  //}
  
  //[실시간 선언 정보판 관련]
  //{
      //[단어 구간 정보 추출]
      //{
          //[2012.05.24.목][추가!!!]{---------------------------------------------
          //실시간으로 [입력지정자] 가 위치한 [단어] 의 [시작/끝:위치] 를 관리.
          //
          //[2012.06.01.금][설명!!!]----------------------------------------------
          //<_EDITBUF_LINE_Out()> 에서 [실시간 선언 정보판:대상단어] 를 지정할때
          //<_wordStartIndex/_wordEndIndex> 정보를 사용하므로 항상 수집해 놓는다.
          //}---------------------------------------------------------------------

          STR_Get_WordBound(_editbuf, _filesize, _caretindex,
                            &_wordStartIndex,
                            &_wordEndIndex);

      //}

      //[실시간 선언 정보판 감추기]
      //{
          //[2012.05.24.목][추가!!!]{----------------------------
          //[실시간 선언 정보판] 이 보이는 경우만 처리하고
          //처리후 반드시 [단어지정] 을 위하여 [입력지정자] 가
          //위치한행만 다시 그린다.
          //
          //더불어, <info_tree_Form->_AutoHide_WordBound()> 에서
          //기존 [단어 구간] 을 벗어난 경우는 자동으로 감춰진다.
          //}----------------------------------------------------

          if(info_tree_Form != NULL)
          {
            if((info_tree_Form->Visible == true) &&
               //[2012.06.01.금][추가!!!]
               //<_AutoHide_WordBound()> 함수 사용 허가상태만 처리.
               (info_tree_Form->_sw_AutoHide_WordBound == true))
            {
              //현재 [단어 구간 정보] 전달.
              info_tree_Form->_AutoHide_WordBound(_wordStartIndex, _wordEndIndex);

              //현재 [입력지정자] 가 위치한 행만 다시 그린다.
              _EditBuf_LineText(_row, false);

            }

          }

      //}
      
  //}    

}

bool __fastcall Teditor_edit_Form::_EditBuf_LineStr_Delete(//[삭제] 할 위치.
                                                           int  pDelIndex,
                                                           //[삭제] 할 크기.
                                                           int  pDelSize)
{
  //[2012.02.01.수][생성!!!]{------------------------------------------------------
  //현재 [저장소] 상의 지정 위치에서 지정 크기 만큼 문자열을 삭제.
  //
  //<_EditBuf_LineStr_Insert()> 함수와 [대칭] 적으로 만들어진 함수로
  //<_LineBlock_MoveRL_Left()> 함수를 만드는 중 필요성이 있어 새로 만드는 것.
  //
  //실제로는 <_EDITBUF_MOONJA_Delete()> 함수를 참고하여 만든다.
  //<_EDITBUF_MOONJA_Delete()> 함수의 [문자열판] 으로 생각하면 된다.
  //<memmove()> 를 사용하여 [문자열 끌어당기기] 방식으로 처리한다.
  //
  //[주의!!!]----------------------------------------------------------------------
  //이 함수는 <_caretindex> 를 수정하지 않으며 문자열에 CRLF 가 존재해서는 안된다.
  //
  //[2012.05.24.목][수정!!!]-------------------------------------------------------
  //[2012.06.01.금][수정!!!]-------------------------------------------------------
  //}------------------------------------------------------------------------------

  //[VAR]
  //{
      int  i;

      //전달받은 문자열의 길이.
      int  size;

  //}

//[2012.05.31.목][임시문장]
//msg_msg_Form->_PrintAddLine(0, "_EditBuf_LineStr_Delete");

  //[삭제]
  //{
      //[주의!!!]{-----------------------------------------------------------------------
      //[삭제크기] 가 [편집기] 에서 처리중인 문자열의 길이를 넘어서는 안된다.
      //<_filesize> 에는 문자열 끝의 '\0' 까지 포함되므로 항상 '\0' 은 남아 있어야 한다.
      //}--------------------------------------------------------------------------------

      if(_filesize > pDelSize)
      {
        //[문자열 끌어 당기기]
        //{
            //[!]{--------------------------------------------------------------
            //<memmove()> 함수로 [문자열] 을 [삭제 크기] 만큼 [끌어당기기] 하면
            //자동으로 [삭제] 되는 방법을 사용한다.
            //}-----------------------------------------------------------------

            memmove(&(_editbuf[pDelIndex]), &(_editbuf[pDelIndex + pDelSize]),
                    //삭제할 크기 다음 부분부터 문서 끝까지 당겨 붙인다.
                    _filesize - (pDelIndex + pDelSize));
        //}

        //[문서량 수정]
        //{
            //삭제한 문자의 길이만큼 [문서양] 이 준다.
            _filesize -= pDelSize;

        //}

      }
      else
      {
        //더이상 처리할수 없으므로 종료.
        return(false);

      }

  //}

  //[실시간 선언 정보판 관련]
  //{
      //[단어 구간 정보 추출]
      //{
          //[2012.05.24.목][추가!!!]{---------------------------------------------
          //실시간으로 [입력지정자] 가 위치한 [단어] 의 [시작/끝:위치] 를 관리.
          //
          //[2012.06.01.금][설명!!!]----------------------------------------------
          //<_EDITBUF_LINE_Out()> 에서 [실시간 선언 정보판:대상단어] 를 지정할때
          //<_wordStartIndex/_wordEndIndex> 정보를 사용하므로 항상 수집해 놓는다.
          //}---------------------------------------------------------------------

          STR_Get_WordBound(_editbuf, _filesize, _caretindex,
                            &_wordStartIndex,
                            &_wordEndIndex);

      //}

      //[실시간 선언 정보판 감추기]
      //{
          //[2012.05.24.목][추가!!!]{----------------------------
          //[실시간 선언 정보판] 이 보이는 경우만 처리하고
          //처리후 반드시 [단어지정] 을 위하여 [입력지정자] 가
          //위치한행만 다시 그린다.
          //
          //더불어, <info_tree_Form->_AutoHide_WordBound()> 에서
          //기존 [단어 구간] 을 벗어난 경우는 자동으로 감춰진다.
          //}----------------------------------------------------

          if(info_tree_Form != NULL)
          {
            if((info_tree_Form->Visible == true) &&
               //[2012.06.01.금][추가!!!]
               //<_AutoHide_WordBound()> 함수 사용 허가상태만 처리.
               (info_tree_Form->_sw_AutoHide_WordBound == true))
            {
              //현재 [단어 구간 정보] 전달.
              info_tree_Form->_AutoHide_WordBound(_wordStartIndex, _wordEndIndex);

              //현재 [입력지정자] 가 위치한 행만 다시 그린다.
              _EditBuf_LineText(_row, false);

            }

          }

      //}

  //}

  return(true);

}

void __fastcall Teditor_edit_Form::_CARET_MOONJA_Insert(short  pCODE,
                                                        //[수정이력] 을 적용하는 경우는 true.
                                                        bool   pHistoryAdd)
{
  //[2007.01.12.금][생성!!!]{----------------------------------------------------------------
  //현재 _caretindex 위치에 전달받은 문자를 끼워넣는다.
  //
  //단, _EditBuf_Text() 처럼 전체를 다시 출력하는 것이 아니라 지정 일부를 출력하여
  //연속하여 문자를 계속 출력하는 경우, 처리 시간을 최소한으로 줄이기 위한 것이다.
  //또한, 이 함수는 한 행에서만 유효하다.
  //
  //[2007.02.01.목][수정!!!]-----------------------------------------------------------------
  //이전에는 [입력지정자] 의 위치에서부터 행 끝가지 다시 출력했으나 [문법강조] 를 위하여
  //행의 처음부터 완전히 다시 출력하는 것으로 수정한다.
  //
  //[2007.02.13.화][추가!!!]-----------------------------------------------------------------
  //[선택영역] 이 이미 존재하는 경우 별도 처리를 추가한다.
  //
  //[2007.02.20.화][수정!!!]-----------------------------------------------------------------
  //[선택영역] 을 _SELECT_Delete() 함수로 삭제할때 [선택영역] 안에 CRLF 가 삭제되면
  //전체 행수가 줄어 들게 되므로 관리변수인 _linecount 를 여기서 직접 수정해 주어야 한다.
  //삭제된 CRLF 개수는 _SELECT_Delete() 함수에서 반환된다.
  //
  //[2007.02.27.화][수정!!!]-----------------------------------------------------------------
  //먼저 삭제하기전에 [입력지정자] 를 [선택영역] 시작 위치로 이동하게 되는데,
  //이때 _EDIT_CaretPos() 함수안에서 [선택영역] 이 해제 되므로 정보를 상실하게 된다.
  //따라서, _SELECT_Get_StartEndIndex() 에서 얻어진 정보를 _EDIT_CaretPos() 함수 처리 후
  //다시 설정해 줌으로써 [선택영역] 을 _SELECT_Delete() 함수로 삭제할수 있게 만든다.
  //
  //<Shift> 를 눌러 [대문자] 등을 입력하는 경우는 _shift_down == true 가 되어
  //_EDIT_CaretPos() 함수에서 [선택영역] 이 해제 되지 않으므로 깜박거리는 문제가 발생한다.
  //따라서, 이 함수처럼 [문자] 를 입력하는 경우는 자동적으로 [선택영역] 이 해제되어야 하므로
  //여기서 _shift_down = false 해주어 _EDIT_CaretPos() 함수 처리시 자동으로 [선택영역] 이
  //해제 되도록 만든다.
  //
  //[2007.03.10.토][수정!!!]-----------------------------------------------------------------
  //_EditBuf_Text() 등 다시 그리는 함수가 중복 처리 되어 깜박이는 문제를 수정하였다.
  //
  //[2007.03.26.월][수정!!!]-----------------------------------------------------------------
  //[전체배경사용] 의 경우는 이 창에 해당하는 부분이 보여지도록 한다.
  //
  //[2009.05.03.일][중요수정!!!]-------------------------------------------------------------
  //[수정이력] 을 저리하기 위하여 수정시 수정되는 상태를 정리하여 저장하는 기능을 추가한다.
  //[선택영역] 이 존재하는 경우는 삭제될 [선택영역] 을 먼저 [수집] 하고 다음에 [문자] 를
  //수집해야 한다.
  //
  //[2018.02.14.수][중요수정!!!]*************************************************************
  //UBUNTU 등 리눅스에서 "Wine" 으로 구동하는 경우 [한글입력문제] 가 발생하여 이를 수정.
  //[문제] : [한/영키:한글] 인 경우는 한글뿐 아니라 Ascii 문자도 전부 2 바이트로 넘어 온다.
  //         즉, WM_CHAR 에서 처리되지 않고 WM_IME_COMPOSITION 에서 한글과 같이 처리되어
  //         전체 2 바이트가 된다.
  //         '6' 문자의 경우 0x36 의 값이나 실제는 0x3600 으로 넘어 오게 된다.
  //         이경우 [상위 바이트] 만으로 1 바이트 코드가 되도록 내부 적으로 선행처리를 수행
  //         하도록 수정한다.
  //}----------------------------------------------------------------------------------------

  //[방법]
  //{
      //------------------------------------------------------------------------------
      //(1) : _editbuf[] 상에 문자를 집어 넣는다.
      //(2) : 문자열이 출력될 부분을 전부 지운다.(해당 행에 국한된다.)
      //      이는 처리 시간을 최소한으로 줄이기 위하여 출력을 시작할 문자의 위치부터
      //      이 행의 끝까지 전부 지운다.
      //(3) : _editbuf[] 상의 지정 범위의 문자열을 출력한다.
      //(4) : [입력지정자] 를 현재 입력한 문자열 다음위치로 이동시킨다.
      //      이는 이미 모든 처리를 할수 있는 _KEY_Right() 함수로 간단하게 처리한다.
      //------------------------------------------------------------------------------
  //}

  //[VAR]
  //{
      TRect             rect;
      int               i;

      int               r_lineendindex;

      struct CARETINFO  select_start;
      struct CARETINFO  select_end;

      int               crlf_count = 0;

      bool              editbuftext = true;

      //_CARET_ViewAlways() 함수가 내부적으로 동작한 경우 true 로 된다.
      bool              caret_viewalways = false;
      bool              select_use       = false;

      //[2012.06.11.월][추가!!!]
      //<_CommentBlock_Info()> 의 결과를 보관.
      bool   cmtBlkChanged = false;

  //}

  //[<Shift> 해제]
  //{
      //[2007.02.27.화][추가!!!]{----------------------------------------------------
      //<Shift> 는 문자 입력시 무효하므로 [선택영역] 의 해제를 위하여 기록을 지운다.
      //이렇게 하는 이유는 _EDIT_CaretPos() 함수안의 [선택영역] 처리부분을 참고한다.
      //}----------------------------------------------------------------------------

      _shift_down = false;

  //}

  //[선택영역 처리]
  //{
      //[설명]{-----------------------------------------------
      //[2007.02.13.화]
      //1. 일단 [선택영역] 구간을 _editbuf[] 상에서 삭제한다.
      //2. <Key> 동작을 처리한다.
      //}-----------------------------------------------------

      //먼저 [입력지정자] 의 위치를 [선택영역] 시작 지점으로 이동시킨다.
      if(_SELECT_Get_StartEndIndex(&select_start, &select_end) != true) goto KEY_DEFAULT;


      if(pHistoryAdd == true)
      {
        //[수정이력][2009.05.03.일][추가!!!]{************************
        //[선택영역] 은 여기서 [삭제] 되므로 이를 기록한다.
        //[선택영역] 은 항상 관리 상태이므로 간단하게 처리 가능하다.
        //[수집 시작 위치]-------------------------------------------
        _history.strStartIndex = select_start.caret_index;
        //[수집 끝 위치]---------------------------------------------
        _history.strEndIndex   = select_end.caret_index;
        //[수집]-----------------------------------------------------
        //[삭제] 수정이다.
        History_Add('-', 's');
        //}**********************************************************

      }


      //[입력지정자 위치 수정]
      //{
          //[선택영역] 이 있는 경우만 처리한다.
          //[입력지정자] 위치는 select_startindex 위치가 된다.(작은 index)
          _caretindex = select_start.caret_index;
          _caret_x    = select_start.caret_x;
          _caret_y    = select_start.caret_y;

          //[입력지정자 위치 조정]
          _EDIT_CaretPos(_caret_x, _caret_y);

      //}

      //[입력지정자 항상 보이기]
      //{
          _editbuf_text_no = true;
          //{
              //키는 항상 눈에 보이는 위치에 있어야 한다.
              caret_viewalways = _CARET_ViewAlways(false);
              //<키> 를 처리하지 않고 여기서 종료 되므로 이곳에서 한번 실행해 주어야 한다.
          //}
          _editbuf_text_no = false;

      //}

      //[선택영역 정보 복구]
      //{
          //위에서 처리한 _EDIT_CaretPos() 에서 해제된 [선택영역] 의 정보를 다음 처리부에서
          //삭제할수 있도록 이미 얻어 놓은 정보로 복구한다.
          _select_start = select_start;
          _select_end   = select_end;

      //}

      //[선택영역] 삭제.
      if(_SELECT_Delete(&select_start, &crlf_count) == true)
      {
        //[선택영역] 을 처리했다는 것을 알린다.
        select_use = true;

        //[행수 수정]
        //{
            //CRLF 가 삭제된 것이 있는 경우만 수정한다.
            if(crlf_count > 0) { _linecount -= crlf_count; }

        //}

        //[묶음주석 정보 수집]
        //{
            //[2012.06.10.일][추가!!!]{---------------
            //반드시 [수정] 된 후에 [수집] 해야 한다.
            //}---------------------------------------

            //계속 이어지므로 여기서는 처리하지 않는다.
            //[2012.06.12.화][수정!!!]
            //부분정보 수집----------------------v
            //cmtBlkChanged = _CommentBlock_Info(true);

        //}

        //[삭제 반영]{----------------------------------------------------------------------
        //이 문자키의 경우는 한줄만 다시 그려지므로 여기서 처리하지 않으면
        //삭제된 내용이 반영되지 않는다.(반드시 여기서 처리한다)
        //_EditBuf_Text();
        //[2007.03.10.토][수정!!!]
        //여기서 처리 하지 않고 중복 처리를 방지하기 위하여 이 함수 끝에서 한번만 처리한다.
        //}---------------------------------------------------------------------------------

        //[수직스크롤설정]
        //{
            //수정된 행이 있는 경우는 문서행수가 바뀌었으므로 [수직스크롤] 을
            //새로 설정해 주어야 한다.
            //일반 키입력시에는 행이 바뀌지 않으므로 행이 바뀐 이곳에서 처리한다.
            if(crlf_count > 0) { _Scroll_Resize(); }

        //}

      }

      goto CONTINUE;

  //}

  //[순수한 KEY 처리]-----------------------------------------------------------

  KEY_DEFAULT:

  //[입력지정자 항상 보이기]
  //{
      _editbuf_text_no = true;
      //{
          //키는 항상 눈에 보이는 위치에 있어야 한다.
          caret_viewalways = _CARET_ViewAlways(false);
      //}
      _editbuf_text_no = false;

  //}

  CONTINUE:

  //[wine 에서 구동하는 경우를 위한 수정]
  //{
      //[2018.02.14.수][중요수정!!!]-------------------------------------------------------------
      //UBUNTU 등 리눅스에서 "Wine" 으로 구동하는 경우 [한글입력문제] 가 발생하여 이를 수정.
      //[문제] : [한/영키:한글] 인 경우는 한글뿐 아니라 Ascii 문자도 전부 2 바이트로 넘어 온다.
      //         즉, WM_CHAR 에서 처리되지 않고 WM_IME_COMPOSITION 에서 한글과 같이 처리되어
      //         전체 2 바이트가 된다.
      //         '6' 문자의 경우 0x36 의 값이나 실제는 0x3600 으로 넘어 오게 된다.
      //         이경우 [상위 바이트] 만으로 1 바이트 코드가 되도록 내부 적으로 선행처리를 수행
      //         하도록 수정한다.
      //
      //[한글] 은 항상 2바이트 값이다.
      //}----------------------------------------------------------------------------------------

      if((pCODE & 0x00ff) == 0)
      {
        //[하위 바이트] 가 0 이면 Ascii 로 보고 1바이트 코드로 변환.
        pCODE = (pCODE >> 8) & 0x00ff;

      }

  //}

  //[한/영 상태]
  //{
      //[2018.02.14.수][추가!!!]

      if(_ide_option->wine == true)
      {
        if((pCODE & 0xff00) == 0) { editor_info_Form->_HanEngLabel_Eng(); }
        else                      { editor_info_Form->_HanEngLabel_Han(); }

      }

  //}

  if(pHistoryAdd == true)
  {
    //[수정이력][2009.05.03.일][추가!!!]{**************************
    //[수집] 시작 위치를 기록한다.
    //[수집 시작 위치]---------------------------------------------
    _history.strStartIndex = _caretindex;
    //[수집 끝 위치]-----------------------------------------------
    //[한글(2Byte)/영문(1Byte)] 의 경우를 구분하여 처리한다.
    if(pCODE & 0xff00) { _history.strEndIndex = _caretindex + 2; }
    else               { _history.strEndIndex = _caretindex + 1; }
    //}************************************************************

  }


  //[버퍼 수정]
  //{
      //_editbuf[] 상의 _caretindex 위치에 일단 문자를 집어 넣는다.
      _EDITBUF_MOONJA_Insert(_caretindex, pCODE);

  //}


  if(pHistoryAdd == true)
  {
    //[수정이력][2009.05.03.일][추가!!!]{**************************
    //[저장소] 가 수정된 이후에야 [문자열] 을 수집 가능하다.
    //[수집]-------------------------------------------------------
    //[추가] 수정이다.
    History_Add('+', 'c');
    //}************************************************************

  }

  //[묶음주석 정보 수집]
  //{
      //[2012.06.10.일][추가!!!]{---------------
      //반드시 [수정] 된 후에 [수집] 해야 한다.
      //}---------------------------------------

      //[2012.06.12.화][수정!!!]
      //부분정보 수집--------------------v
      cmtBlkChanged = _CommentBlock_Info(true);

  //}

  //[출력 위치 지우기]
  //{
      if((caret_viewalways == false) && (select_use == false))
      {
        //[영역구하기]
        //{
            rect      = _bmp_->Canvas->ClipRect;
            rect.Left = _text_org_x;
            rect.Top  = _text_org_y + _caret_y;

        //}

        //[출력영역지우기]
        //{
            if(IDE_BACKBMP_entire)
            {
              //이 경우는 한개의 그림을 여러창에서 나누어 사용해야 한다.

              //[표시 시작 위치 계산]
              //{
                  //크기가 변경되는 경우는 전체 바탕그림을 표시하는 시작 위치도 변경된다.
                  //이는 마치 한개의 동일한 그림 위에 투명하게 위치하는 것같은 느낌을 주기 위한 것이다.
                  _bmporg_x = ide_editor_Form->Left - d_border_width + 1;

                  _bmporg_y = 0;

              //}

              //현재 [입력지정자] 가 위치한 행만 지운다.
              //그냥 지우면 배경 그림이 지워지므로 반드시 배경 그림을 사용하여 지워야 한다.
              BitBlt(_bmp_->Canvas->Handle, rect.Left, rect.Top, rect.Right - rect.Left, _line_height,
                     _bmp_back_->Canvas->Handle, _bmporg_x + rect.Left, _bmporg_y + rect.Top, SRCCOPY);

            }
            else
            {
              //현재 [입력지정자] 가 위치한 행만 지운다.
              //그냥 지우면 배경 그림이 지워지므로 반드시 배경 그림을 사용하여 지워야 한다.
              BitBlt(_bmp_->Canvas->Handle, rect.Left, rect.Top, rect.Right - rect.Left, _line_height,
                     _bmp_back_->Canvas->Handle, rect.Left - d_gutter_width, rect.Top, SRCCOPY);

            }

        //}

      }

  //}

  //[정지줄 처리]
  //{
      //[2007.04.16.월][추가!!!]{----------------------------------------------
      //현재 행이 [정지점] 이 있는 행인 경우는 배경에 [정지줄] 을 만들어 준다.
      //}----------------------------------------------------------------------

      _BREAKPOINT_Edit_Verify_Draw(_caret_y / _line_height);

  //}

  if((caret_viewalways == false) && (select_use == false))
  {
    //[현재행 시작 위치 구하기]
    //{
        STR_Get_ThisLineStartIndex(_editbuf, _caretindex, &_linestartindex);

    //}

    //[문자열 출력]
    //{
        //x 가 적용될 절대 기준 위치를 설정해 놓는다.
        _font.margin_size = _text_org_x;

        //현재 [입력지정자] 가 위치한 행 시작부터 끝까지 해당 문자열을 다시 츨력한다.
        //행 처음부터 다시 출력해야 [문법강조] 를 수행할수 있다.
        //입력위치 x 의 _text_org_x 는 이미 _font.margin_size 에 적용된 상태이므로 따로 더할필요는 없다.
        _EDITBUF_LINE_Out(0, _text_org_y + _caret_y, _linestartindex, &r_lineendindex);

    //}

    //[검증창 반영]
    //{
        //[2007.04.09.월][추가!!!]{---------------------------------------------
        //[검증창] 은 모든 내용이 다 그려진 다음에 가장 나중에 출력되어야 한다.
        //다른 내용 가장 위에 위치해야 하므로.
        //}---------------------------------------------------------------------

        BitBlt(_bmp_->Canvas->Handle, 0, rect.Top, d_gutter_width, _line_height + 1,
               _bmp_debug->Canvas->Handle, 0, rect.Top, SRCCOPY);

    //}

  }

  //[입력지정자 이동]
  //{
      //[!]{---------------------------------------------------------------------------------
      //현재 [입력지정자] 위치에 한개의 문자를 입력했으므로 이 문자 다음위치로 이동시킨다.
      //단, 문자를 입력하는 과정이므로 false 로 설정하여 <Shift-Key> 로 문자를 입력하는 경우
      //[선택영역] 을 생성하지 않고 [문자] 를 입력할수 있게 한다.
      //}------------------------------------------------------------------------------------

      _KEY_Right(false, false);

  //}

  //[수정된 영역만 다시 그리기]
  //{
      if((caret_viewalways == false) && (select_use == false) &&
         //[2012.06.11.월][추가!!!]
         //[묶음주석] 정보가 수정된 경우는 [전체 다시 그리기] 로 처리해야 한다.
         (cmtBlkChanged != true))
      {
        //[!]{---------------------------------------------------------------------------------
        //_Draw() 함수를 사용하여 전체를 다시 그리지 않고 수정된 행만 다시 그려준다.
        //이는 키가 계속눌려서 문자가 계속 출력되는 경우 처리속도를 최대한 높이기 위한 것이다.
        //}------------------------------------------------------------------------------------

        BitBlt(this->Canvas->Handle, rect.Left, rect.Top, rect.Right - rect.Left, _line_height + 1,
               _bmp_->Canvas->Handle, rect.Left, rect.Top, SRCCOPY);

      }
      else
      {
        _EditBuf_Text();

      }

  //}

  return;

}

//------------------------------------------------------------------------------
//[문자열관련]------------------------------------------------------------------
//------------------------------------------------------------------------------

void __fastcall Teditor_edit_Form::_WORD_LineGet(char  *pSTR,
                                                 int    pINDEX,
                                                 char   rWORD[],
                                                 int   *rWORDindex,
                                                 int   *rWORDlength)
{
  //[2007.01.24.수][생성!!!]{-------------------------------------------------------
  //pSTR[] 상의 지정 위치부터 처음 발견되는 단어를 추출하여 반환한다.
  //이 함수는 [문법강조] 를 처리 하기 위하여 사용되며, [한국형-C] 언어에서는
  //[한글] 이름도 지원한다.
  //[CRLF], ['\0'], [이름], [//], ["], ['], [\"], [\'], [#], [기타기호등] 이 단어로
  //반환되는데 이는 각각 문자색을 적용하는데 중요한 정보를 갖기 때문이다.
  //처리 속도를 빠르게 하기 위하여 다른 자세한 것은 여기서 구분하지 않는다.

  //[2007.01.27.토][추가!!!]--------------------------------------------------------
  //[공백] 이 계속 이어지는 경우나 [공백] 도 전부 단어로 취급한다.

  //[2007.01.31.수][수정!!!]--------------------------------------------------------
  //[//], ["], ['], [\"], [\'], [#] 은 각각이 단어로 완전히 분리 되어야 한다.
  //abc//efg 는 "abc" "//" "efg" 의 3 개 단어로 구분되어야한다.
  //
  //[2011.05.11.수][중요수정!!!]----------------------------------------------------
  //"...\\" 이나 '...\\' 의 경우 [\\] 를 [특수문자] 로 처리하지 않아서 이 경우
  //[\"] 나 [\'] 로 인식되어 [색동문자] 가 제대로 처리되지 않는 문제가 있었다.
  //[\\] 를 별도의 [특수문자] 로 처리하여 문제를 해결하였다.
  //}-------------------------------------------------------------------------------

  //[VAR]
  //{
      int   i = pINDEX;

      //문자가 저장되는 시작 위치로 이 위치에는 항상 '\0' 이 있다.
      //즉, w 값이 결국 반환하는 단어의 길이가 된다.
      int   w = 0;

      char  wkind = 0;
      //'n' : 이름
      //'s' : 기호
      //'_' : 공백

  //}

  //[초기화]
  //{
      //현재는 아무 문자도 없는 상태.
      rWORD[0]       = '\0';
      (*rWORDindex)  = i;
      (*rWORDlength) = w;

  //}

  START:

  //문자 code 를 추출한다.
  if     ((pSTR[i] == ' ') || (pSTR[i] == '\t'))
  {
    if(rWORD[0] == '\0')
    {
      //지금 문자가 첫문자인 경우는 [공백] 조합이 시작됬음을 알린다.
      wkind = '_';

      //현재 문자의 시작 위치를 기록한다.
      (*rWORDindex) = i;

      //초기화.
      w        = 0;
      rWORD[w] = '\0';

    }
    else
    {
      if(wkind != '_')
      {
        //이 경우는 [name/symbol] 조함중 다른 문자가 발견된 것이므로 여기서 조합된 단어를 반환한다.

        //[단어반환]{----------------------------------------------
        //이미 단어가 완성된 상태이므로 여기서 바로 종료하면 된다.
        return;
        //}--------------------------------------------------------

      }

    }

    //[단어합성]
    //{
        //1 byte 만 처리한다.

        rWORD[w++] = pSTR[i++];
        rWORD[w]   = '\0';

        (*rWORDlength) = w;

    //}

    //계속 문자를 검사한다.
    goto START;

  }
  else if(pSTR[i] == '\0')
  {
    //현재 문서의 끝이라면 행의 끝이므로 더이상 처리하지 않고
    //현재 단어를 반환한다.

    if(rWORD[0] == '\0')
    {
      //첫문자가 '\0' 인 경우도 이것을 문자로 반환해야 한다.
      (*rWORDindex) = i;

      rWORD[w]   = '\0';

      (*rWORDlength) = w;

    }

    //[단어반환]{----------------------------------------------
    //이미 단어가 완성된 상태이므로 여기서 바로 종료하면 된다.
    return;
    //}--------------------------------------------------------

  }
  else if((pSTR[i] == 0x0d) || (pSTR[i + 1] == 0x0a))
  {
    //현재 행의 끝이라면 더이상 처리 하지 않고 조합된 단어를 즉시 반환한다.

    if(rWORD[0] == '\0')
    {
      //첫문자가 CRLF 인 경우는 이 code 를 그대로 단어로 반환해 준다.
      (*rWORDindex) = i;

      rWORD[w++] = 0x0d;
      rWORD[w++] = 0x0a;
      rWORD[w]   = '\0';

      (*rWORDlength) = w;

    }

    //[단어반환]{----------------------------------------------
    //이미 단어가 완성된 상태이므로 여기서 바로 종료하면 된다.
    return;
    //}--------------------------------------------------------

  }
  else if(pSTR[i] < 0)
  {
    //[한글] 은 2 byte 를 같이 처리한다.

    if(rWORD[0] == '\0')
    {
      //지금 문자가 첫문자인 경우는 [name] 조합이 시작됬음을 알린다.
      wkind = 'n';

      //현재 문자의 시작 위치를 기록한다.
      (*rWORDindex) = i;

      //초기화.
      w        = 0;
      rWORD[w] = '\0';

    }
    else
    {
      if(wkind != 'n')
      {
        //이 경우는 [space/symbol] 조함중 다른 문자가 발견된 것이므로 여기서 조합된 단어를 반환한다.

        //[단어반환]{----------------------------------------------
        //이미 단어가 완성된 상태이므로 여기서 바로 종료하면 된다.
        return;
        //}--------------------------------------------------------

      }

    }

    //[단어합성]
    //{
        //한글은 2 byte 를 처리해야 한다.

        rWORD[w++] = pSTR[i++];
        rWORD[w++] = pSTR[i++];
        rWORD[w]   = '\0';

        (*rWORDlength) = w;

    //}

    //계속 문자를 검사한다.
    goto START;

  }
  else if((pSTR[i] == '_') || (('0' <= pSTR[i]) && (pSTR[i] <= '9')) ||
          (('a' <= pSTR[i]) && (pSTR[i] <= 'z')) || (('A' <= pSTR[i]) && (pSTR[i] <= 'Z')))
  {
    //[한글] 을 제외하고 순순하게 [이름] 을 구성할수 있는 문자인경우.

    if(rWORD[0] == '\0')
    {
      //지금 문자가 첫문자인 경우는 [name] 조합이 시작됬음을 알린다.
      wkind = 'n';

      //현재 문자의 시작 위치를 기록한다.
      (*rWORDindex) = i;

      //초기화.
      w        = 0;
      rWORD[w] = '\0';

    }
    else
    {
      if(wkind != 'n')
      {
        //이 경우는 [space/symbol] 조함중 다른 문자가 발견된 것이므로 여기서 조합된 단어를 반환한다.

        //[단어반환]{----------------------------------------------
        //이미 단어가 완성된 상태이므로 여기서 바로 종료하면 된다.
        return;
        //}--------------------------------------------------------

      }

    }

    //[단어합성]
    //{
        //1 byte 만 처리한다.

        rWORD[w++] = pSTR[i++];
        rWORD[w]   = '\0';

        (*rWORDlength) = w;

    //}

    //계속 문자를 검사한다.
    goto START;

  }


  else if((pSTR[i] == '\\') && (pSTR[i + 1] == '\\')) //[\\] 의 경우.
  {
    //[2011.05.11.수][중요수정!!!][임시처리!!!]{-------------------------------------
    //{ "...\\" } 나 { '...\\' } 의 경우는 문자열이 마감된 것으로 보아야 하는데
    //이전에는 [\\] 처리 부가 없어서 [\\] 를 인식 못하게 되어 결국 [\"] 나 [\'] 으로
    //인식되어 문자열이 마무리 되지 않은 것으로 인식되는 문제가 있었다.
    //따라서, 임시적으로 [\\] 를 한개 단어로 보고 마무리 하도록 처리한다.
    //결과는 이상없이 되었다.
    //[문서] 상에서 [\\] 를 연속적으로 사용하는 경우는 거의 없으므로,
    //지나치가 단어가 구분되어 생기는 문제를 걱정할 필요는 없다.
    //결국에는 문자열 안의 일반 문자처럼 취급된다.
    //
    // [\\] 단어처리.
    //실제 문서상에서는 "...\\..." 가 되고 표시는 [\] 한개만 나온다.
    //특수문자라 복수개로 사용하게 된다.
    //}-------------------------------------------------------------------------------

    if(wkind == 0)
    {
      //이 단어가 처음 시작하는 경우.
      (*rWORDindex) = i;

      rWORD[w++] = '\\';
      rWORD[w++] = '\\';
      rWORD[w]   = '\0';

      (*rWORDlength) = w;

    }

    //[단어반환]{----------------------------------------------
    //이미 단어가 완성된 상태이므로 여기서 바로 종료하면 된다.
    return;
    //}--------------------------------------------------------

  }


  //분리 기호의 경우는 문자를 직접 검사하여 처리한다.
  else if((pSTR[i] == '/') && (pSTR[i + 1] == '/'))
  {
    // [//] 단어처리.
    if(wkind == 0)
    {
      //이 단어가 처음 시작하는 경우.
      (*rWORDindex) = i;

      rWORD[w++] = '/';
      rWORD[w++] = '/';
      rWORD[w]   = '\0';

      (*rWORDlength) = w;

    }

    //[단어반환]{----------------------------------------------
    //이미 단어가 완성된 상태이므로 여기서 바로 종료하면 된다.
    return;
    //}--------------------------------------------------------

  }
  else if((pSTR[i] == '/') && (pSTR[i + 1] == '*'))
  {
    // [/*] 단어처리.
    if(wkind == 0)
    {
      //이 단어가 처음 시작하는 경우.
      (*rWORDindex) = i;

      rWORD[w++] = '/';
      rWORD[w++] = '*';
      rWORD[w]   = '\0';

      (*rWORDlength) = w;

    }

    //[단어반환]{----------------------------------------------
    //이미 단어가 완성된 상태이므로 여기서 바로 종료하면 된다.
    return;
    //}--------------------------------------------------------

  }
  else if((pSTR[i] == '*') && (pSTR[i + 1] == '/'))
  {
    // [*/] 단어처리.
    if(wkind == 0)
    {
      //이 단어가 처음 시작하는 경우.
      (*rWORDindex) = i;

      rWORD[w++] = '*';
      rWORD[w++] = '/';
      rWORD[w]   = '\0';

      (*rWORDlength) = w;

    }

    //[단어반환]{----------------------------------------------
    //이미 단어가 완성된 상태이므로 여기서 바로 종료하면 된다.
    return;
    //}--------------------------------------------------------

  }
  else if((pSTR[i] == '\\') && (pSTR[i + 1] == '\"'))
  {
    // [\"] 단어처리.
    if(wkind == 0)
    {
      //이 단어가 처음 시작하는 경우.
      (*rWORDindex) = i;

      rWORD[w++] = '\\';
      rWORD[w++] = '\"';
      rWORD[w]   = '\0';

      (*rWORDlength) = w;

    }

    //[단어반환]{----------------------------------------------
    //이미 단어가 완성된 상태이므로 여기서 바로 종료하면 된다.
    return;
    //}--------------------------------------------------------

  }
  else if((pSTR[i] == '\\') && (pSTR[i + 1] == '\''))
  {
    // [\'] 단어처리.
    if(wkind == 0)
    {
      //이 단어가 처음 시작하는 경우.
      (*rWORDindex) = i;

      rWORD[w++] = '\\';
      rWORD[w++] = '\'';
      rWORD[w]   = '\0';

      (*rWORDlength) = w;

    }

    //[단어반환]{----------------------------------------------
    //이미 단어가 완성된 상태이므로 여기서 바로 종료하면 된다.
    return;
    //}--------------------------------------------------------

  }
  else if(pSTR[i] == '\"')
  {
    // ["] 단어처리.
    if(wkind == 0)
    {
      //이 단어가 처음 시작하는 경우.
      (*rWORDindex) = i;

      rWORD[w++] = '\"';
      rWORD[w]   = '\0';

      (*rWORDlength) = w;

    }

    //[단어반환]{----------------------------------------------
    //이미 단어가 완성된 상태이므로 여기서 바로 종료하면 된다.
    return;
    //}--------------------------------------------------------

  }
  else if(pSTR[i] == '\'')
  {
    // ['] 단어처리.
    if(wkind == 0)
    {
      //이 단어가 처음 시작하는 경우.
      (*rWORDindex) = i;

      rWORD[w++] = '\'';
      rWORD[w]   = '\0';

      (*rWORDlength) = w;

    }

    //[단어반환]{----------------------------------------------
    //이미 단어가 완성된 상태이므로 여기서 바로 종료하면 된다.
    return;
    //}--------------------------------------------------------

  }
  else if(pSTR[i] == '#')
  {
    // [#] 단어처리.
    if(wkind == 0)
    {
      //이 단어가 처음 시작하는 경우.
      (*rWORDindex) = i;

      rWORD[w++] = '#';
      rWORD[w]   = '\0';

      (*rWORDlength) = w;

    }

    //[단어반환]{----------------------------------------------
    //이미 단어가 완성된 상태이므로 여기서 바로 종료하면 된다.
    return;
    //}--------------------------------------------------------

  }

  else
  {
    //그밖의 기호, 영문등을 처리한다.
    //특별하게 단어로 규정되지 않는 이상 전부 단어로 이어 붙인다.

    if(rWORD[0] == '\0')
    {
      //지금 문자가 첫문자인 경우는 [symbol] 조합이 시작됬음을 알린다.
      wkind = 's';

      //현재 문자의 시작 위치를 기록한다.
      (*rWORDindex) = i;

      //초기화.
      w        = 0;
      rWORD[w] = '\0';

    }
    else
    {
      if(wkind != 's')
      {
        //이 경우는 [space/name] 조함중 다른 문자가 발견된 것이므로 여기서 조합된 단어를 반환한다.

        //[단어반환]{----------------------------------------------
        //이미 단어가 완성된 상태이므로 여기서 바로 종료하면 된다.
        return;
        //}-------------------------------------------------------=

      }

    }

    //[단어합성]
    //{
        //1 byte 만 처리한다.

        rWORD[w++] = pSTR[i++];
        rWORD[w]   = '\0';

        (*rWORDlength) = w;

    //}

    //[특별 단어 검사]
    //{
        //해당되는 단어를 찾은 경우는 즉시 종료한다.
        if(STR_Match(rWORD, "//")   == true) return;
        if(STR_Match(rWORD, "\"")   == true) return;
        if(STR_Match(rWORD, "\'")   == true) return;
        if(STR_Match(rWORD, "\\\"") == true) return;
        if(STR_Match(rWORD, "\\\'") == true) return;
        if(STR_Match(rWORD, "#")    == true) return;

    //}

    //계속 문자를 검사한다.
    goto START;

  }

  return;

}

void __fastcall Teditor_edit_Form::_MOONJACONFIG_LineGet(int   pLINEstartindex,
                                                         int  *rLineEndIndex)
{
  //[2007.01.23.화][생성!!!]{-------------------------------------------------------------------
  //현재 행의 문자열을 분석하여 [문법강조] 등의 특성을 적용하여 해당 정보 구조체에 기록해 준다.
  //대상은 _editbuf[] 이고 처리 결과는 _wordconfig[] 전역 구조체에 저장된다.
  //행을 구분하는 것은 이 함수안에서 자체적으로 처리 되어야한다.
  //즉, CRLF, '\0' 인 경우는 현재 행이 끝난 것으로 보고 종료한다.
  //단, [선택영역] 은 여기서 처리하지 않는다.
  //
  //[2007.02.03.토][추가!!!]--------------------------------------------------------------------
  //[2진수], [16진수] 의 경우도 지정된 색으로 입힌다.
  //
  //[2009.03.31.화][수정!!!]
  //각각의 문서 유형에 따라 다른 색정의를 적용한다.
  //이는 [검증] 시에 <*.c>, <*.gasm>, <*.gcsm> 등 3 종류의 중요문서를 사용하며 각각의 구성이
  //다르므로 각각 [색동문자] 정의를 달리하여 가독성을 높이고 혼란을 막기 위한 것이다.
  //<*.txt> 등 기타 다른 문서는 아예 [색동문자] 를 적용핳지 않는다.
  //[문서종류] 는 이미 [전용속성] 에 저장되 있으므로 이를 참고하면 된다.
  //
  //[2009.05.28.목][추가!!!]--------------------------------------------------------------------
  //<*.gtxt> 문서 처리를 수정한다.
  //
  //[2011.05.27.금][수정!!!]--------------------------------------------------------------------
  //<*.gobj>, <*.glib> 문서를 여는 경우도 추가한다.
  //이는 [검증] 시 [함수묶음] 을 열어서 보여줄때 필요하다.
  //
  //[2011.06.06.월][수정!!!]--------------------------------------------------------------------
  //<*.gtmp> 문서를 여는 경우도 추가한다.
  //}-------------------------------------------------------------------------------------------

  //[주의!!!]{-------------------------------------------------------------------
  //_wordconfig[] 의 정보를 사용하여 문자열을 출력하게 되므로,
  //행의 끝을 알수 있는 CRLF, '\0' 도 같이 처리해 주어야 한다.
  //
  //[2007.02.03.토][참고!!!]-----------------------------------------------------
  //STR_Match() 로 2 문자 이하의 단어를 검사하는 경우는 문자를 각각 비교하는것에
  //비하여 시간 낭비일수 있다.
  //}----------------------------------------------------------------------------

  //[VAR]
  //{
      char   word[OPT_str_default_size*10];
      int    wordindex;
      int    wordlength;

      int    i;

      //단어구분을 위한것.
      char   wkind = 0;

      bool   first_word = true;

      //[2009.04.01.수][추가!!!]
      int    lineEndIndex;

  //}

  //[초기화]
  //{
      _wordconfig_count = 0;

  //}

  //[문법강조처리]
  //{
      //[2009.03.31.화][중요수정!!!]{-------
      //각각의 문서에 따라 다르게 처리한다.
      //}-----------------------------------

      //<*.c> 인가?
      if((_fileKind == d_Editor_FileKind_c) || (_fileKind == d_Editor_FileKind_gtxt))
      {
        //<*.c> [색동문자] 전문 처리 함수를 사용한다.
        _MoonjaConfig_LineGet_C(pLINEstartindex, rLineEndIndex);

      }
      //<*.gasm> 인가?
      else if(_fileKind == d_Editor_FileKind_gasm)
      {
        //<*.gasm> [색동문자] 전문 처리 함수를 사용한다.
        _MoonjaConfig_LineGet_Gasm(pLINEstartindex, rLineEndIndex);

      }
      //<*gcsm> 인가?
      else if(_fileKind == d_Editor_FileKind_gcsm)
      {
        //<*.gcsm> [색동문자] 전문 처리 함수를 사용한다.
        _MoonjaConfig_LineGet_Gcsm(pLINEstartindex, rLineEndIndex);

      }
      else if(_fileKind == d_Editor_FileKind_obj)
      {
        //[2011.05.27.금][추가!!!]{--------------------------------
        //<*.gobj>, <*.glib> [색동문자] 전문 처리 함수를 사용한다.
        //}--------------------------------------------------------

        _MoonjaConfig_LineGet_Obj(pLINEstartindex, rLineEndIndex);

      }
      else if(_fileKind == d_Editor_FileKind_gtmp)
      {
        //[2011.06.06.월][추가!!!]{----------------------
        //<*.gtmp> [색동문자] 전문 처리 함수를 사용한다.
        //}----------------------------------------------

        _MoonjaConfig_LineGet_Gtmp(pLINEstartindex, rLineEndIndex);

      }
      //일반 문서인가?
      else if(_fileKind == d_Editor_FileKind_default)
      {
        //<일반문서> [색동문자] 전문 처리 함수를 사용한다.
        _MoonjaConfig_LineGet_Default(pLINEstartindex, rLineEndIndex);

      }

  //}

  //여기까지 모든 정보가 처리되어 _wordconfig[] 안에 저장되었다.

  return;

}

void __fastcall Teditor_edit_Form::_MoonjaConfig_LineGet_C(int   pLineStartIndex,
                                                           int  *rLineEndIndex)
{
  //[2009.04.01.수][생성!!!]{-------------------------------------------------------
  //<*.c> 형식의 [색동문자] 를 처리한다.
  //
  //[2011.05.11.수][수정!!!]--------------------------------------------------------
  //[라벨] 형식의 경우도 [색동문자] 를 적용한다.
  //
  //[2011.06.04.토][수정!!!]--------------------------------------------------------
  //[주석] 문을 이전과 달리 [한줄주석] 과 [묶음주석] 으로 구분하여 처리한다.
  //
  //더불어, [특수주석문] 의 경우 별도의 [색동문자] 를 적용하도록 수정한다.
  //
  //[2011.06.16.목][수정!!!]--------------------------------------------------------
  //[한줄 주석] 문 처리를 한꺼번에 [행단위] 로 하는 경우는 이 [한줄 주석] 안에
  //[형광문자] 가 들어 있는 경우는 처리가 되지 않는다.
  //이는 [형광문자] 는 [단어] 단위로 처리되기 때문이다.
  //따라서, [한줄주석] 도 [특수주석] 문을 제외하도는 다른 부분은 전부 [단어] 단위로
  //처리하는 것으로 수정한다.
  //
  //[2011.08.20.토][수정!!!]--------------------------------------------------------
  //<라벨:> 을 처리시 <default:> 까지 라벨로 보는 것을 발견하였다.
  //<default:> 는 <switch...case> 문에 사용되는 [예약어] 이므로 제외시킨다.
  //
  //[2012.06.08.금][수정!!!]--------------------------------------------------------
  //}-------------------------------------------------------------------------------

  //[VAR]
  //{
      char   word[OPT_str_default_size*10];
      int    wordindex;
      int    wordlength;

      int    i = pLineStartIndex;

      //단어구분을 위한것.
      char   wkind = 0;

      bool   first_word = true;

      //[2011.05.11.수][추가!!!]
      //공백이나 무효를 제외하고 실제적인 단어수만 기록한다.
      int    wordCount = 0;

      //[2011.06.04.토][추가!!!]
      char   tempStr[OPT_lineStrSize];

      //[2011.08.20.토][추가!!!]{-----------------------------------------
      //이전 단어가 [예약어] 였다면 <true> 가 된다.
      //이는 [예약어] 부분에서 <true> 로 처리하고, 다른 처리분에서 처리후
      //<false> 로 재설정한다.
      bool   isBeforeWordKeyword = false;
      //}-----------------------------------------------------------------

      //[2018.10.01.월][추가!!!]
      int    c = 0;

  //}

  //[초기화]
  //{
      _wordconfig_count = 0;

  //}

  //[문법강조처리]
  //{
      for(i = pLineStartIndex; ; i = (wordindex + wordlength))
      {
        //[단어 정보 추출]{----------------------------------------
        _WORD_LineGet(_editbuf, i, word, &wordindex, &wordlength);
        //}--------------------------------------------------------

        if(((word[0] == 0x0d) && (word[1] == 0x0a)) || (word[0] == '\0'))
        {
          //이 경우는 완전히 현재 검사하는 행이 끝난 것이므로 처리를 종료한다.
          break;

        }

        //[묶음주석 처리]
        //{
            //[2009.06.02.화]{----------------------------------------------------------
            //{/* ... */} 와 같은 [묶음주석] 을 처리한다.
            //이미 모든 정보는 다 정리되 있으므로 현재 행이 여기에 걸쳐 있는지 확인하고
            //해당 처리를 수행하면 된다.
            //}-------------------------------------------------------------------------

            if(_CommentBlock_Check_Word(wordindex) == true)
            {
              //현재 단어는 [묶음주석] 안에 있는 것이다.
              goto COMMENT_BLOCK;

            }

        //}

        //[종류판별]
        //{
            //이미 설정 정보가 있는 경우는 바로 해당 처리부로 이동해야 한다.

            switch(wkind)
            {
              //이미 [지시어] 안의 단어라면, 이 행의 끝까지 [지시어] 색으로 처리한다.
              case '#' : goto DIRECTIVE;  break;

              //현재 [문자열] 안이다.
              case 's' : goto STRING;     break;

              //현재 [문자상수] 안이다.
              case 'c' : goto CHAR;       break;

              //[2011.06.04.토][수정!!!]
              //[주석] => [한줄주석] 으로 교체한다.
              //현재 [한줄 주석문] 안이므로, [주석] 해제되기 전까지 [주석문] 색으로 처리한다.
              case 'j' : goto COMMENT_LINE;    break;

              //[2011.06.04.토][추가!!!]
              //[한줄주석] 과 [묶음주석] 을 구분하므로 [묶음주석] 을 추가한다.
              case 'b' : goto COMMENT_BLOCK;    break;

            }

        //}

        SPACE:
        {
          if(word[0] == ' ')
          {
            //[!]{-----------------------------------------------------------------------------
            //[공백] 이 계속되는 경우도 단어로 취급되므로 이 경우는 기본 설정으로 처리한다.
            //이 경우는 첫문자만 검사하면 된다.
            //[공백] 도 단어로 추출은 되므로 단어검사부분에서 쓸데없는 시간 낭비를 막기 위하여
            //여기서 따로 처리한다.
            //}--------------------------------------------------------------------------------

            _wordconfig[_wordconfig_count].index       = wordindex;
            _wordconfig[_wordconfig_count].length      = wordlength;
            _wordconfig[_wordconfig_count].front_color = IDE_COLOR_1;
            _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
            _wordconfig[_wordconfig_count].transparent = true;
            _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;

            _wordconfig_count++;

            //[2011.08.20.토][추가!!!]{-----
            //이 단어는 [예약어] 가 아니다.
            isBeforeWordKeyword = false;
            //}-----------------------------

            continue;

          }

        }

        KEYWORD:
        {
          if(STR_Match(word, "break")  || STR_Match(word, "else")    || STR_Match(word, "switch")   ||
             STR_Match(word, "case")   || STR_Match(word, "return")  || STR_Match(word, "continue") ||
             STR_Match(word, "for")    || STR_Match(word, "default") || STR_Match(word, "goto")     ||
             STR_Match(word, "do")     || STR_Match(word, "if")      || STR_Match(word, "while")    ||
             STR_Match(word, "struct") || STR_Match(word, "union")   || STR_Match(word, "double")   ||
             STR_Match(word, "int")    || STR_Match(word, "long")    || STR_Match(word, "char")     ||
             STR_Match(word, "float")  || STR_Match(word, "short")   || STR_Match(word, "unsigned") ||
             STR_Match(word, "signed") || STR_Match(word, "void")    || STR_Match(word, "include")  ||
             STR_Match(word, "define") || STR_Match(word, "undef")   ||
             //[2009.09.23.수][추가!!!]
             //true, false 는 사용자가 정의해야 하는 값이나 사용빈도가 높으므로 구분시킨다.
             //[2018.07.08.일][수정!!!]
             //"true" 는 "[기계닉스] 정의 [type]" 과 같은 색으로 정의.
             /*STR_Match(word, "true")   ||*/ STR_Match(word, "false") ||
             //[2009.10.07.수][추가!!!]
             //bool 은 사용자가 정의해야 하는 값이지만 사용빈도가 높으므로 구분시킨다.
             STR_Match(word, "bool")   ||
             //[2012.02.09.목][추가!!!]
             //<sizeof> 도 지원한다.
             //현 시점에서 처리중이지만 미리 [색동문자] 에 등록해 놓는다.
             STR_Match(word, "sizeof") ||
             //[2015.01.18.일][추가!!!]
             //맷돌-IDE 에서 C/C++/JAVA 문서도 열어 보기 위하여 C/C++/JAVA 예약어 전체 추가.
             STR_Match(word, "abstract")   || STR_Match(word, "boolean")  || STR_Match(word, "byte")         ||
             STR_Match(word, "catch")      || STR_Match(word, "class")    || STR_Match(word, "const")        ||
             STR_Match(word, "extends")    || STR_Match(word, "final")    || STR_Match(word, "finally")      ||
             STR_Match(word, "implements") || STR_Match(word, "import")   || STR_Match(word, "instanceof")   ||
             STR_Match(word, "interface")  || STR_Match(word, "native")   || STR_Match(word, "new")          ||
             STR_Match(word, "null")       || STR_Match(word, "package")  || STR_Match(word, "private")      ||
             STR_Match(word, "protected")  || STR_Match(word, "public")   || STR_Match(word, "static")       ||
             STR_Match(word, "strictfp")   || STR_Match(word, "super")    || STR_Match(word, "synchronized") ||
             STR_Match(word, "this")       || STR_Match(word, "throw")    || STR_Match(word, "throws")       ||
             STR_Match(word, "transient")  || STR_Match(word, "try")      || STR_Match(word, "volatile")     ||
             STR_Match(word, "asm")        || STR_Match(word, "friend")   || STR_Match(word, "auto")         ||
             STR_Match(word, "delete")     || STR_Match(word, "template") || STR_Match(word, "register")     ||
             STR_Match(word, "inline")     || STR_Match(word, "enum")     || STR_Match(word, "typedef")      ||
             STR_Match(word, "extern")     || STR_Match(word, "operator") || STR_Match(word, "virtual")      ||
             //[2018.04.28.토][추가!!!]
             STR_Match(word, "NULL"))
          {
            //[예약어] 는 지정색으로 칠한다.
            _wordconfig[_wordconfig_count].index       = wordindex;
            _wordconfig[_wordconfig_count].length      = wordlength;
            _wordconfig[_wordconfig_count].front_color = _ide_option->color_Keyword;;
            _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
            _wordconfig[_wordconfig_count].transparent = true;
            _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_bold;

            _wordconfig_count++;

            //[2011.08.20.토][추가!!!]{---
            //이 단어는 [예약어] 다.
            isBeforeWordKeyword = true;
            //}---------------------------

            first_word = false;

            //[2011.05.11.수][추가!!!]{---
            wordCount++;
            //}---------------------------

            continue;

          }
          //[2018.04.28.토][추가!!!]{-------
          //[기계닉스] 정의 [type] 도 추가.
          //}-------------------------------
          else if(STR_Match(word, "t_알림문") || STR_Match(word, "t_알림문64") || STR_Match(word, "t_알림문_GUI") ||
                  STR_Match(word, "t_u1")     || STR_Match(word, "t_s1")       || STR_Match(word, "t_u2")         ||
                  STR_Match(word, "t_s2")     || STR_Match(word, "t_u4")       || STR_Match(word, "t_s4")         ||
                  STR_Match(word, "t_u8")     || STR_Match(word, "t_s8")       || STR_Match(word, "t_f")          ||
                  STR_Match(word, "t_d")      || STR_Match(word, "t_생성자")   ||
                  STR_Match(word, "true"))
          {
            //[기계닉스:특수 type] 을 [지정색] 으로 칠한다.
            _wordconfig[_wordconfig_count].index       = wordindex;
            _wordconfig[_wordconfig_count].length      = wordlength;
            _wordconfig[_wordconfig_count].front_color = 0xe2;//0xc8;//_ide_option->color_Keyword;;
            _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
            _wordconfig[_wordconfig_count].transparent = true;
            _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_bold;

            _wordconfig_count++;

            //[2011.08.20.토][추가!!!]{---
            //이 단어는 [예약어] 다.
            isBeforeWordKeyword = true;
            //}---------------------------

            first_word = false;

            //[2011.05.11.수][추가!!!]{---
            wordCount++;
            //}---------------------------

            continue;

          }
          //[2018.10.01.월][추가!!!]{----
          //[기계닉스:특수함수] 도 추가.
          //}----------------------------
          else if(STR_Match(word, "event"))
          {
            //[!]{----------------------------------------------------------
            //"__" 로 시작하는 특수함수(기계닉스:GUI 등) 과 같은 형식 적용.
            //}-------------------------------------------------------------

            _wordconfig[_wordconfig_count].index       = wordindex;
            _wordconfig[_wordconfig_count].length      = wordlength;
            _wordconfig[_wordconfig_count].front_color = 0x00424242;
            _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
            _wordconfig[_wordconfig_count].transparent = true;
            _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_bold;

            _wordconfig_count++;

            //이 단어는 [예약어] 다.
            isBeforeWordKeyword = true;

            first_word = false;

            wordCount++;

            continue;

          }

        }

        __NAME:
        {
          //[2018.09.30.일][추가!!!]{--------------------------------------------------------
          //"__" 로 시작하는 특수 [함수](기계닉스:GUI:API 등)의 경우도 [색동문자] 로 처리.
          //[폼디자이너] 의 [맷돌-IDE] 통합 지원을 위하여 추가.
          //
          //단, "__func" 형식의 [이름] 으로 반드시 [함수] 만 해당해야 하므로 "(" 이 뒤에
          //따르는 경우만 해당.
          //
          //[방법!!!]------------------------------------------------------------------------
          //
          //[행] 단위로 처리하므로 직접 단어 끝위치 부터 검사.
          //
          //1) [공백] 을 제외하고 "(" 이 발견되는 경우는 적용.
          //
          //2) [공백] 이외에 다른 문자가 먼저 발견되는 경우나, 행끝, 문서 끝에 도달한 경우는
          //   해당하지 않는 것으로 간주.
          //
          //}--------------------------------------------------------------------------------

          if     ((word[0] == '_') && (wordlength >= 3) && (word[1] == '_'))
          {
            //["(" 이 뒤따르는지 확인]
            //{
                //현재 단어 끝 위치 부터 검색 시작.
                for(c = wordindex + wordlength; ; c++)
                {
                  if     (_editbuf[c] == '(')
                  {
                    //"(" 문자를 발견한 것이므로 적용.
                    break;

                  }
                  else if(_editbuf[c] == ' ')
                  {
                    //[공백] 인 경우는 계속 검사.

                  }
                  else if(((word[0] == 0x0d) && (word[1] == 0x0a)) || (word[0] == '\0'))
                  {
                    //이 경우는 현재 행 끝까지 검사해도 "(" 문자가 없는 것으로 보고 다음 처리로 넘긴다.
                    goto _NAME_;

                  }
                  else
                  {
                    //다른 문자가 발견된 경우도 역시 해당하지 않는것.
                    goto _NAME_;

                  }

                }

            //}

            _wordconfig[_wordconfig_count].index       = wordindex;
            _wordconfig[_wordconfig_count].length      = wordlength;
            _wordconfig[_wordconfig_count].front_color = 0x00424242;
            _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
            _wordconfig[_wordconfig_count].transparent = true;
            _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_bold;

            _wordconfig_count++;

            //이 단어는 [예약어] 가 아님.
            isBeforeWordKeyword = false;

            first_word = false;

            wordCount++;

            continue;

          }
          
        }

        _NAME_:
        {
          //[2018.09.30.일][추가!!!]{--------------------------------------------------------
          //"_func_" 형식의 특수 [함수](기계닉스:GUI:API 등)의 경우도 [색동문자] 로 처리.
          //[폼디자이너] 의 [맷돌-IDE] 통합 지원을 위하여 추가.
          //
          //단, "_func_" 형식의 [이름] 으로 반드시 [함수] 만 해당해야 하므로 "(" 이 뒤에
          //따르는 경우만 해당.
          //
          //[방법!!!]------------------------------------------------------------------------
          //
          //[행] 단위로 처리하므로 직접 단어 끝위치 부터 검사.
          //
          //1) [공백] 을 제외하고 "(" 이 발견되는 경우는 적용.
          //
          //2) [공백] 이외에 다른 문자가 먼저 발견되는 경우나, 행끝, 문서 끝에 도달한 경우는
          //   해당하지 않는 것으로 간주.
          //
          //}--------------------------------------------------------------------------------

          if     ((word[0] == '_') && (wordlength >= 3) && (word[wordlength - 1] == '_'))
          {
            //["(" 이 뒤따르는지 확인]
            //{
                //현재 단어 끝 위치 부터 검색 시작.
                for(c = wordindex + wordlength; ; c++)
                {
                  if     (_editbuf[c] == '(')
                  {
                    //"(" 문자를 발견한 것이므로 적용.
                    break;

                  }
                  else if(_editbuf[c] == ' ')
                  {
                    //[공백] 인 경우는 계속 검사.

                  }
                  else if(((word[0] == 0x0d) && (word[1] == 0x0a)) || (word[0] == '\0'))
                  {
                    //이 경우는 현재 행 끝까지 검사해도 "(" 문자가 없는 것으로 보고 다음 처리로 넘긴다.
                    goto d_NAME;

                  }
                  else
                  {
                    //다른 문자가 발견된 경우도 역시 해당하지 않는것.
                    goto d_NAME;

                  }

                }

            //}

            _wordconfig[_wordconfig_count].index       = wordindex;
            _wordconfig[_wordconfig_count].length      = wordlength;
            _wordconfig[_wordconfig_count].front_color = 0xd0;//0x000059b2;//0x007171ff;//IDE_COLOR_1;//0xe1;
            _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
            _wordconfig[_wordconfig_count].transparent = true;
            _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;

            _wordconfig_count++;

            //이 단어는 [예약어] 가 아님.
            isBeforeWordKeyword = false;

            first_word = false;

            wordCount++;

            continue;

          }

        }

        d_NAME:
        {
          //[2018.10.01.월][추가!!!]{----------------------
          //"d_name" 형식으로 [기계닉스:이름정의] 인 경우.
          //
          //[형식] 일뿐 실제 [이름정의] 가 아닐수 있다.
          //}----------------------------------------------

          if     ((word[0] == 'd') && (wordlength >= 3) && (word[1] == '_'))
          {
            _wordconfig[_wordconfig_count].index       = wordindex;
            _wordconfig[_wordconfig_count].length      = wordlength;
            _wordconfig[_wordconfig_count].front_color = 0x00008000;
            _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
            _wordconfig[_wordconfig_count].transparent = true;
            _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;

            _wordconfig_count++;

            //이 단어는 [예약어] 가 아님.
            isBeforeWordKeyword = false;

            first_word = false;

            wordCount++;

            continue;

          }

        }

        NUMBER:
        {
          if     ((word[0] == '0') && ((word[1] == 'b')||(word[1] == 'B')))
          {
            //[2진수] 는 지정색으로 칠한다.
            _wordconfig[_wordconfig_count].index       = wordindex;
            _wordconfig[_wordconfig_count].length      = wordlength;
            _wordconfig[_wordconfig_count].front_color = _ide_option->color_BinWord;
            _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
            _wordconfig[_wordconfig_count].transparent = true;
            _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;

            _wordconfig_count++;

            //[2011.08.20.토][추가!!!]{-----
            //이 단어는 [예약어] 가 아니다.
            isBeforeWordKeyword = false;
            //}-----------------------------

            first_word = false;

            //[2011.05.11.수][추가!!!]{---
            wordCount++;
            //}---------------------------

            continue;

          }
          else if((word[0] == '0') && ((word[1] == 'x')||(word[1] == 'X')))
          {
            //[16진수] 는 지정색으로 칠한다.
            _wordconfig[_wordconfig_count].index       = wordindex;
            _wordconfig[_wordconfig_count].length      = wordlength;
            _wordconfig[_wordconfig_count].front_color = _ide_option->color_HexWord;
            _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
            _wordconfig[_wordconfig_count].transparent = true;
            _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;

            _wordconfig_count++;

            //[2011.08.20.토][추가!!!]{-----
            //이 단어는 [예약어] 가 아니다.
            isBeforeWordKeyword = false;
            //}-----------------------------

            first_word = false;

            //[2011.05.11.수][추가!!!]{---
            wordCount++;
            //}---------------------------

            continue;

          }

        }

        DEFAULT:
        {
          //[구분처리]
          //{
              if(STR_Match(word, "#"))
              {
                //이 단어가 첫 단어라면 이 단어부터 이 행의 끝까지는 전부 [지시문] 이므로
                //[지시어] 색으로 적용한다.
                if((wkind == 0) && (first_word == true))
                {
                  //현재 단어부터 행 끝가지 [지시어] 가 된다.
                  wkind = '#';
                  goto DIRECTIVE;

                }

              }
              else if(STR_Match(word, "\""))
              {
                goto STRING;

              }
              else if(STR_Match(word, "\'"))
              {
                goto CHAR;

              }
              else if(STR_Match(word, "//"))
              {
                //이 단어부터 행의 끝까지 전부 [주석문] 이 된다.
                //행 끝가지 무조건 적용 되므로 해제할 필요는 없다.
                wkind = 'j';
                goto COMMENT_LINE;

              }
              else if(STR_Match(word, "/*"))
              {
                //[!]{-----------------------------------------------------------
                //이 단어부터 "*/" 까지 전부 [주석문] 이 된다.
                //행 끝가지 무조건 적용 되므로 해제할 필요는 없다.
                //
                //[2011.06.04.토][수정!!!]---------------------------------------
                //[한줄주석] 과 [묶음주석] 을 구분하므로 'j' => 'b' 로 교체한다.
                //}--------------------------------------------------------------

                wkind = 'b';
                goto COMMENT_BLOCK;

              }

              //[2011.05.11.수][추가!!!]
              else if(STR_Match(word, ":"))
              {
                //[라벨로 처리하나?]
                //{
                    //[2011.05.11.수][중요추가!!!]{--------------------------------------------------
                    //이 경우는 이전 단어가  [라벨] 로 표할수 있는 단어인지 검사한뒤
                    //단순하게 [라벨] 로 처리 할수 있는 최소 조건만 된다면 [라벨] 형식으로 표시한다.
                    //
                    //1) 앞단어가 [행의 첫번째 단어] 인경우.
                    //
                    //2) 앞단어가 [공백] 이어서는 안된다.
                    //
                    //C 언어 문법상의 [라벨] 이 아니라, [색동문자] 를 적용하기 위한 것이므로
                    //[문법] 적으로 까다롭게 검사하지는 않는다.
                    //}------------------------------------------------------------------------------

                    if(//현재 [문자열], [주석] 안이 아닌 일반 문자 상태인 경우인가?
                       (wkind == 0) &&
                       //이전 단어가 첫 단어 인가?
                       (wordCount == 1) &&
                       //위치가 음수가 되면 안된다.
                       (wordindex > 0) &&
                       //[2011.08.20.토][추가!!!]{-----------------------
                       //이전 단어가 [예약어] 였다면 처리해서는 안된다.
                       //이는 <default:> 의 경우를 걸러내기 위한 것이다.
                       (isBeforeWordKeyword != true)
                       //}-----------------------------------------------
                      )
                    {
                      if(//이전 문자가 반드시 [공백] 이 아니어야 한다.
                         (_editbuf[wordindex - 1] != ' ') &&
                         //이전에 단어가 반드시 한개는 있어야 한다(<_wordconfig_count - 1> 로 검사하므로).
                         (_wordconfig_count> 0))
                      {
                        //[이전 단어 정보 교체]
                        //{
                            //[!]{------------------------------------------
                            //이전 단어의 속성을 [라벨] 로 강제 재설정한다.
                            //}---------------------------------------------

                            _wordconfig[_wordconfig_count - 1].front_color = 0x008000ff;
                            _wordconfig[_wordconfig_count - 1].back_color  = IDE_COLOR_2;
                            _wordconfig[_wordconfig_count - 1].style       = d_FONTSTYLE_bold;

                        //}

                        //[현재 ":" 문자 속성 설정]
                        //{
                             //[!]{--------------------------------
                             //현재 ":" 문자도 [라벨] 로 설정한다.
                             //}-----------------------------------

                            _wordconfig[_wordconfig_count].index       = wordindex;
                            _wordconfig[_wordconfig_count].length      = wordlength;
                            _wordconfig[_wordconfig_count].front_color = 0x008000ff;
                            _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
                            _wordconfig[_wordconfig_count].transparent = true;
                            _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_bold;

                            _wordconfig_count++;

                            //[2011.08.20.토][추가!!!]{-----
                            //이 단어는 [예약어] 가 아니다.
                            isBeforeWordKeyword = false;
                            //}-----------------------------

                            first_word = false;

                            //[2011.05.11.수][추가!!!]{---
                            wordCount++;
                            //}---------------------------

                            //더이상 처리하지 않고 다음으로 넘긴다.
                            continue;

                        //}

                      }

                  //}

                }

              }

          //}

          //여기까지 온것은 [일반문자] 이다.

          //[일반문자] 는 기본설정.
          _wordconfig[_wordconfig_count].index       = wordindex;
          _wordconfig[_wordconfig_count].length      = wordlength;
          _wordconfig[_wordconfig_count].front_color = IDE_COLOR_1;
          _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
          _wordconfig[_wordconfig_count].transparent = true;
          _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;

          _wordconfig_count++;

          //[2011.08.20.토][추가!!!]{-----
          //이 단어는 [예약어] 가 아니다.
          isBeforeWordKeyword = false;
          //}-----------------------------

          first_word = false;

          //[2011.05.11.수][추가!!!]{---
          wordCount++;
          //}---------------------------

          continue;

        }

        DIRECTIVE:
        {
          //[주석문 시작 검사]
          //{
              //만일 [지시문] 안이라도 [주석문] 이 시작되면 이때부터는 [주석문] 이 된다.
              if(STR_Match(word, "//"))
              {
                //이 단어부터 행의 끝까지 전부 [한줄주석문] 이 된다.
                //행 끝가지 무조건 적용 되므로 해제할 필요는 없다.
                wkind = 'j';
                goto COMMENT_LINE;

              }

          //}

          _wordconfig[_wordconfig_count].index       = wordindex;
          _wordconfig[_wordconfig_count].length      = wordlength;
          _wordconfig[_wordconfig_count].front_color = _ide_option->color_Directive;//IDE_COLOR_directive;
          _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
          _wordconfig[_wordconfig_count].transparent = true;
          _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;

          _wordconfig_count++;

          //[2011.08.20.토][추가!!!]{-----
          //이 단어는 [예약어] 가 아니다.
          isBeforeWordKeyword = false;
          //}-----------------------------

          first_word = false;

          //[2011.05.11.수][추가!!!]{---
          wordCount++;
          //}---------------------------

          continue;

        }

        STRING:
        {
          _wordconfig[_wordconfig_count].index       = wordindex;
          _wordconfig[_wordconfig_count].length      = wordlength;
          _wordconfig[_wordconfig_count].front_color = _ide_option->color_String;
          _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
          _wordconfig[_wordconfig_count].transparent = true;
          _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;

          _wordconfig_count++;

          //[2011.08.20.토][추가!!!]{-----
          //이 단어는 [예약어] 가 아니다.
          isBeforeWordKeyword = false;
          //}-----------------------------

          first_word = false;

          //[2011.05.11.수][추가!!!]{---
          wordCount++;
          //}---------------------------

          if(STR_Match(word, "\""))
          {
            //이 단어부터 다시 이 단어가 나올때 까지 [문자열] 이 된다.
            if     (wkind == 0)
            {
              //지금 [단어] 를 포함하여 [문자열] 이 시작되었다.
              wkind = 's';

            }
            else if(wkind == 's')
            {
              //현재 단어까지는 [문자열] 이나, 다음 단어를 위하여 해제한다.
              wkind = 0;

            }

          }

          continue;

        }

        CHAR:
        {
          _wordconfig[_wordconfig_count].index       = wordindex;
          _wordconfig[_wordconfig_count].length      = wordlength;
          _wordconfig[_wordconfig_count].front_color = _ide_option->color_Char;
          _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
          _wordconfig[_wordconfig_count].transparent = true;
          _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;

          _wordconfig_count++;

          //[2011.08.20.토][추가!!!]{-----
          //이 단어는 [예약어] 가 아니다.
          isBeforeWordKeyword = false;
          //}-----------------------------

          first_word = false;

          //[2011.05.11.수][추가!!!]{---
          wordCount++;
          //}---------------------------

          if(STR_Match(word, "\'"))
          {
            //이 단어부터 다시 이 단어가 나올때 까지 [문자상수] 가 된다.
            if     (wkind == 0)
            {
              //지금 [단어] 를 포함하여 [문자상수] 가 시작되었다.
              wkind = 'c';

            }
            else if(wkind == 'c')
            {
              //현재 단어까지는 [문자상수] 이나, 다음 단어를 위하여 해제한다.
              wkind = 0;

            }

          }

          continue;

        }

        COMMENT_LINE:
        {
          //[2011.06.04.토][수정!!!]{---------------------------------------------------------
          //[한줄주석] 과 [묶음주석] 을 구분처리 하므로 여기서는 [한줄주석] 만 처리한다.
          //
          //"//" 단어를 검출한뒤 바로 이곳으로 오기 때문에, 여기는 [한줄주석] 의 시작이된다.
          //
          //한줄 주석은 "//" 위치부터 이 행의 끝까지 무조건 [주석] 이 되므로 아예 [단어]
          //단위로 처리하지 않고 여기서 일괄 처리하는 것으로 한다.
          //
          //[특수 주석 문 처리]---------------------------------------------------------------
          //"//[주의]", "//[중요]", "//[참고]", "//[설명]", "//[방법]" 의 4종류는
          //다른 색으로 지정해 준다.
          //"//[...]" 는 주석 그대로 두고 안의 "주의!!!" 같은 [문자열] 만 별도의
          //[색동문자] 를 지정한다.
          //
          //단, 반드시 "//" 바로 다음에 즉, 주석이 시작되는 것만 처리해야 한다.
          //단지 설명시 보다 시인성을 강화하기 위한 것으로 엄밀히 [주석] 이므로
          //너무 정교하게 구현할 필요는 없다.
          //
          //[2011.06.16.목][수정!!!]----------------------------------------------------------
          //[형광문자] 가 [단어] 단위로 처리되므로 이전과 같이 [한행] 전체를 일괄 처리하는
          //방식으로는 [형광문자] 를 처리할수 없게 된다.
          //따라서, [특수주석] 을 제외하고는 다른 주석문은 모두 [단어] 단위로 처리하는 것으로
          //수정한다.
          //}---------------------------------------------------------------------------------

          //[검사 단어 추출]
          //{
              //[2011.06.16.목][참고!!!]{--------------------------------------------------------
              //이 부분은 [한줄 주석] 이 처음 시작되는 부분에서 한번만 검사하게 되는데
              //이는 [특수주석] 처리후 바로 <wkind = 'b'> 로 바꾸어, 다음 부터는 [묶음주석] 으로
              //처리되도록 유도하기 때문이다.
              //}--------------------------------------------------------------------------------

              STR_SubString(//현재 "//" 의 위치부터 문자열 시작으로 본다.
                            &(_editbuf[wordindex]),
                            //"[" 다음 문자의 위치는 <index:3> 이다..
                            3,
                            //추출할 길이("단어" 로 총 4 바이트 고정(한글만 허용)).
                            4,
                            //추출된 [문서이름].
                            tempStr);

          //}

          //[특수 단어 인가?]
          //{
              if(//[2022.01.08.토][추가]{*****************
                 //이 부분이 있어야 //[설명] 만 적용된다.
                 ((&(_editbuf[wordindex]))[2] == '[') &&
                 //}**************************************
                 (STR_Match(tempStr, "주의") || STR_Match(tempStr, "중요") ||
                  STR_Match(tempStr, "참고") || STR_Match(tempStr, "설명") ||
                  STR_Match(tempStr, "방법") || STR_Match(tempStr, "조건") ||
                  STR_Match(tempStr, "수정") || STR_Match(tempStr, "보완") ||
                  //[2018.10.05.금][추가!!!]
                  STR_Match(tempStr, "형식") || STR_Match(tempStr, "구조")) &&
                  //[2012.06.08.금][추가!!!]{------------------------------------------
                  //이 단어에 붙어서 [기호/영문] 이외 다른 [한글] 이 오는 경우는 예외.
                  //[설명문], [설명서] 등은 해당하지 않아야 한다.
                  (_editbuf[wordindex + 7] >= 0)
                  //}------------------------------------------------------------------
                )
              {
                //[!]{----------------------------------------------------------
                //이 경우는 [특수문자열] 에 포함되므로 별도의 처리를 해야 한다.
                //}-------------------------------------------------------------

                //["//[" 까지 처리]
                //{
                    _wordconfig[_wordconfig_count].index       = wordindex;
                    _wordconfig[_wordconfig_count].length      = 3;
                    _wordconfig[_wordconfig_count].front_color = _ide_option->color_Comment;
                    _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
                    _wordconfig[_wordconfig_count].transparent = true;
                    _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;

                    _wordconfig_count++;

                //}

                //["단어!!!" 처리]
                //{
                    _wordconfig[_wordconfig_count].index       = wordindex + 3;
                    _wordconfig[_wordconfig_count].length      = 4;
                    //[2012.05.24.목][수정!!!]{------------------------------------
                    _wordconfig[_wordconfig_count].front_color = clRed;
                    _wordconfig[_wordconfig_count].back_color  = clWhite;
                    _wordconfig[_wordconfig_count].transparent = true;
                    _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_bold;
                    //}------------------------------------------------------------

                    _wordconfig_count++;

                //}

                //[나머지 처리]
                //{
                    //[2011.06.16.목][수정!!!]{-------------------------------------
                    //[형광문자] 등을 처리하기 위하여 [특수주석] 다음의 [주석문] 은
                    //모두 [단어] 단위로 처리해야 한다.
                    //}-------------------------------------------------------------

                    //[특수주석] 을 처리한 다음부터 처리하도록 한다.
                    wordindex += 3;
                    wordlength = 4;

                    //[형식 변경]{-----------------------------------------------------
                    //[특수주석] 은 [한줄주석] 처음에만 한번 오기 때문에 계속 검사하지
                    //않도록 여기서 부터는 [묶음주석] 으로 인식되게 만든다.
                    //이후 부터는 자동으로 [단어] 단위로 처리되게 된다.
                    wkind = 'b';
                    //}----------------------------------------------------------------

                //}

              }
              else if(((&(_editbuf[wordindex]))[2] == '[') &&
                      ((tempStr[0] == '!') || (tempStr[0] == '@') || (tempStr[0] == '#') ||
                       (tempStr[0] == '%') || (tempStr[0] == '+') || (tempStr[0] == '-') ||
                       (tempStr[0] == '?') || (tempStr[0] == '$') || (tempStr[0] == '=') ||
                       (tempStr[0] == '*')) &&
                      //[2012.06.08.금][추가!!!]{--------------------------------------------
                      //이 단어에 붙어서 [기호/영문] 이외 다른 [한글] 이 오는 경우는 예외.
                      //[설명문], [설명서] 등은 해당하지 않아야 한다.
                      //[한글] 은 char 상으로 첫바이트/두번째 바이트 모두 [음수] 이므로 이를
                      //[양수] 로 구분하기 위한것.
                      (_editbuf[wordindex + 4] >= 0)
                      //}--------------------------------------------------------------------
                     )
              {
                //[2022.01.08.토][추가]{---------------------------------------------------------------
                //특수문자의 경우도 [특수주석] 으로 처리한다.
                //주로 설명문에 많이 사용하는 {//[!]...} 를 지원하려다 필요한 더 많은 문자를 추가한다.
                //}------------------------------------------------------------------------------------

                //["//[" 까지 처리]
                //{
                    _wordconfig[_wordconfig_count].index       = wordindex;
                    _wordconfig[_wordconfig_count].length      = 3;
                    _wordconfig[_wordconfig_count].front_color = _ide_option->color_Comment;
                    _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
                    _wordconfig[_wordconfig_count].transparent = true;
                    _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;

                    _wordconfig_count++;

                //}

                //["문자" 처리]
                //{
                    _wordconfig[_wordconfig_count].index       = wordindex + 3;
                    _wordconfig[_wordconfig_count].length      = 1;
                    _wordconfig[_wordconfig_count].front_color = 0x4080ff; //주황색.
                    _wordconfig[_wordconfig_count].back_color  = clWhite;
                    _wordconfig[_wordconfig_count].transparent = true;
                    _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;

                    _wordconfig_count++;

                //}

                //[나머지 처리]
                //{
                    //[!]{---------------------------------------------------------
                    //[형광문자] 등을 처리하기 위하여 [특수주석] 다음의 [주석문] 은
                    //모두 [단어] 단위로 처리해야 한다.
                    //}------------------------------------------------------------

                    //[특수주석] 을 처리한 다음부터 처리하도록 한다.
                    wordindex += 3;
                    wordlength = 1;

                    //[형식 변경]{-----------------------------------------------------
                    //[특수주석] 은 [한줄주석] 처음에만 한번 오기 때문에 계속 검사하지
                    //않도록 여기서 부터는 [묶음주석] 으로 인식되게 만든다.
                    //이후 부터는 자동으로 [단어] 단위로 처리되게 된다.
                    wkind = 'b';
                    //}----------------------------------------------------------------

                //}

              }
              //[yyyy.mm.dd.토]... 형식 확인. 
              else if(((&(_editbuf[wordindex]))[2] == '[') &&
                      ((&(_editbuf[wordindex]))[7] == '.') && ((&(_editbuf[wordindex]))[10] == '.') && ((&(_editbuf[wordindex]))[13] == '.') &&
                      ((&(_editbuf[wordindex]))[16] == ']'))
              {
                //[2022.01.08.토][추가]{---------------------------------------------------------------
                //주석에서 기계닉스 표준 날짜표기 인 {//[yyyy.mm.dd.토]} 에서 "yyyy.mm.dd.토" 이 부분만
                //녹색으로 처리.
                //구체적인 숫자 유무는 확인하지 않고 단지 "." 위치만 확인한다.
                //실제 [주석] 이므로 정확하게 확인할 필요는 없다(보조기능). 
                //}------------------------------------------------------------------------------------

                //["//[" 까지 처리]
                //{
                    _wordconfig[_wordconfig_count].index       = wordindex;
                    _wordconfig[_wordconfig_count].length      = 3;
                    _wordconfig[_wordconfig_count].front_color = _ide_option->color_Comment;
                    _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
                    _wordconfig[_wordconfig_count].transparent = true;
                    _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;

                    _wordconfig_count++;

                //}

                //["yyyy.mm.dd.토" 처리]
                //{
                    _wordconfig[_wordconfig_count].index       = wordindex + 3;
                    _wordconfig[_wordconfig_count].length      = 13;
                    _wordconfig[_wordconfig_count].front_color = clGreen;
                    _wordconfig[_wordconfig_count].back_color  = clWhite;
                    _wordconfig[_wordconfig_count].transparent = true;
                    _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;

                    _wordconfig_count++;

                //}

                //[나머지 처리]
                //{
                    //[!]{---------------------------------------------------------
                    //[형광문자] 등을 처리하기 위하여 [특수주석] 다음의 [주석문] 은
                    //모두 [단어] 단위로 처리해야 한다.
                    //}------------------------------------------------------------

                    //[특수주석] 을 처리한 다음부터 처리하도록 한다.
                    wordindex += 3;
                    wordlength = 13;

                    //[형식 변경]{-----------------------------------------------------
                    //[특수주석] 은 [한줄주석] 처음에만 한번 오기 때문에 계속 검사하지
                    //않도록 여기서 부터는 [묶음주석] 으로 인식되게 만든다.
                    //이후 부터는 자동으로 [단어] 단위로 처리되게 된다.
                    wkind = 'b';
                    //}----------------------------------------------------------------

                //}

              }
              else
              {
                //해당하지 않아 전체 행이 주석문인 경우.
                _wordconfig[_wordconfig_count].index       = wordindex;
                _wordconfig[_wordconfig_count].length      = wordlength;
                _wordconfig[_wordconfig_count].front_color = _ide_option->color_Comment;
                _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
                _wordconfig[_wordconfig_count].transparent = true;
                _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;

                _wordconfig_count++;

                //[형식 변경][2011.06.16.목][추가!!!]{-------------------------------------
                //[한줄 주석] 의 [특수 주석] 이 아닌 경우라도 한어 한개만 처리 하고
                //다음 부터는 무조건 [묶음 주석] 으로 처리한다.
                //이렇게 하지 않는 경우는 [특수 주석] 이 [한줄 주석] 의 중간에 오는 경우도
                //[특수 주석] 으로 처리되는 경우가 발생한다.
                // 
                //[특수주석] 은 [한줄주석] 처음에만 한번 오기 때문에 계속 검사하지
                //않도록 여기서 부터는 [묶음주석] 으로 인식되게 만든다.
                //이후 부터는 자동으로 [단어] 단위로 처리되게 된다.
                //
                wkind = 'b';
                //}------------------------------------------------------------------------

              }

          //}

          //[2011.08.20.토][추가!!!]{-----
          //이 단어는 [예약어] 가 아니다.
          isBeforeWordKeyword = false;
          //}-----------------------------

          first_word = false;

          //[2011.05.11.수][중요 추가/수정!!!]{--------------------------
          ///* ... */ 주석문의 경우는 문장의 첫 부분에 와도 무효이므로
          //[라벨] 의 [첫단어] 검사를 위하여 단어를 0 으로 처리한다.
          //즉, { ....*/ 라벨: } 인 경우 [라벨] 이 첫단어가 되는 것이다.
          wordCount = 0;
          //}------------------------------------------------------------

          //[2011.06.04.토][중요수정!!!]{---------------------------------------------
          //행을 모두 처리하였으므로 바로 종료한다.
          //그렇지 않은 경우는 <for> 처음의 <_WORD_LineGet()> 함수에서 <wordindex> 와
          //<wordlength> 정보가 다시 계산되어 오류가 발생한다.
          //이미 이 [한줄주석] 전체가 한개의 [단어] 로 위에서 처리되었기 때문이다.
          //즉, 여기서는 <continue> 를 사용하지 않고 바로 <for()> 문을 종료해야 한다.
          //          break;
          continue;
          //}-------------------------------------------------------------------------

        }

        COMMENT_BLOCK:
        {
          //[2011.06.04.토][수정!!!]{--------------------------
          //이전과 달리 [한줄주석] 과 [묶음주석] 을 구분하므로
          //[묶음주석] 은 여기서 처리한다.
          //}--------------------------------------------------

          //해당하지 않아 전체 행이 주석문인 경우.
          _wordconfig[_wordconfig_count].index       = wordindex;
          _wordconfig[_wordconfig_count].length      = wordlength;
          _wordconfig[_wordconfig_count].front_color = _ide_option->color_Comment;
          _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
          _wordconfig[_wordconfig_count].transparent = true;
          _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;

          _wordconfig_count++;

          //[2011.08.20.토][추가!!!]{-----
          //이 단어는 [예약어] 가 아니다.
          isBeforeWordKeyword = false;
          //}-----------------------------

          first_word = false;

          //[2011.05.11.수][중요 추가/수정!!!]{--------------------------
          ///* ... */ 주석문의 경우는 문장의 첫 부분에 와도 무효이므로
          //[라벨] 의 [첫단어] 검사를 위하여 단어를 0 으로 처리한다.
          //즉, { ....*/ 라벨: } 인 경우 [라벨] 이 첫단어가 되는 것이다.
          wordCount = 0;
          //}------------------------------------------------------------

          continue;

        }

      }

  //}

  //[행 끝 위치 반환][2009.05.09.토][추가!!!]{--------
  if(rLineEndIndex != NULL) { (*rLineEndIndex) = i; }
  //}-------------------------------------------------

  return;

}

void __fastcall Teditor_edit_Form::_MoonjaConfig_LineGet_Gasm(int   pLineStartIndex,
                                                              int  *rLineEndIndex)
{
  //[2009.04.01.수][생성!!!]{--------------------------------------------------
  //<*.gasm> 문서의 [색동문자] 처리를 수행한다.
  //
  //[201.06.06.월][수정!!!]----------------------------------------------------
  //{ $행번호 } 의 색을 다른 문장이 더 확실하게 보이도록 [은색] 으로 처리한다.
  //}--------------------------------------------------------------------------

  //[VAR]
  //{
      char   word[OPT_str_default_size*10];
      int    wordindex;
      int    wordlength;
      int    lineEndIndex;

  //}

  //[초기화]
  //{
      _wordconfig_count = 0;

  //}

  //[문법강조처리]
  //{
      //[2009.04.01.수][추가!!!]{-------------------------------------------------------
      //이 경우는 [함수라벨], [행번호], [연산자], [명령어] 등 기본적인 처리만 수행한다.
      //<*.c> 와는 달리 정해진 형식으로 문서가 만들어져 있으므로 직접 단어를 추출하여
      //간단하게 처리한다.
      //"[주소] [첫단어] ..." 의 형식으로 모든 처리대상 단어는 이 [첫단어] 위치에 있다.
      //}-------------------------------------------------------------------------------

      //이 행의 끝위치 구하기.
      STR_Get_ThisLineEndIndex(_editbuf, pLineStartIndex, &lineEndIndex);

      //[행 끝 위치 반환][2009.05.09.토][추가!!!]{-------------------
      if(rLineEndIndex != NULL) { (*rLineEndIndex) = lineEndIndex; }
      //}------------------------------------------------------------

      //[처리할 문서가 있는가?]
      //{
          //[!]{---------------------------------------------------------------------
          //처리할 문자열이 없으므로 처리하지 않고 종료한다.
          //
          //[주의!!!]----------------------------------------------------------------
          //이것을 처리하지 않으면 _wordconfig_count 이 0 이 아닌것으로 되므로
          //이 함수를 사용하는 함수에서 계속 처리를 시도하는 [무한반복] 상태가 된다.
          //}------------------------------------------------------------------------

          if(pLineStartIndex >= lineEndIndex) { _wordconfig_count = 0; return; }

      //}

      //단순하게 순서대로 읽어서 처리하면 된다.

      //처음 문자 위치 계산.
      wordindex = pLineStartIndex;

      //[주소처리]
      //{
          //[!]{-------------------------------------------------------------
          //가장 처음에는 주소(16자리) 가 온다.
          //[문서] 의 기본 형식이므로 [단어] 를 추출하지 않고 바로 처리한다.
          //}----------------------------------------------------------------

          //길이 구하기(주소는 무조건 16 Byte 길이를 갖는다).
          wordlength = 16;

          //[색동문자 설정]
          //{
              //문자 : 기본 문자색.
              //바탕 : 은색.
              //형식 : 일반굵기.

              _wordconfig[_wordconfig_count].index       = wordindex;
              _wordconfig[_wordconfig_count].length      = wordlength;
              _wordconfig[_wordconfig_count].front_color = clGray;
              _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
              _wordconfig[_wordconfig_count].transparent = true;//false;
              _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;
              _wordconfig_count++;

          //}

          //다음 문자의 시작 위치 계산.
          wordindex += wordlength;

      //}

      //[주소 다음 공백 한개 처리]
      //{
          //[주소] 다음에는 1개의 [공백] 이 있으므로 이를 처리한다.

          //[공백] 1개 뿐이다.
          wordlength = 1;

          //[색동문자 설정]
          //{
              //문자 : 기본 문자색.
              //바탕 : 기본.
              //형식 : 일반굵기.

              _wordconfig[_wordconfig_count].index       = wordindex;
              _wordconfig[_wordconfig_count].length      = wordlength;
              _wordconfig[_wordconfig_count].front_color = IDE_COLOR_1;
              _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
              _wordconfig[_wordconfig_count].transparent = true;
              _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;
              _wordconfig_count++;

          //}

          //다음 문자의 시작 위치 계산.
          wordindex += wordlength;

      //}

      //[두번째 단어 구분 처리]
      //{
          //[주소] 다음의 [첫 단어] 만 처리 대상이 되므로 이의 종류를 구분하여 처리한다.

          //[단어 추출]
          //{
              STR_GetLineWordBuf(_editbuf, wordindex, 0, &wordindex, word);

          //}

          //정해진 문자만 검색하는것으로 간단하게 종류를 구분할수 있다.
          if     (word[0] == ':')
          {
            //[함수라벨] 인 경우.

            //길이 얻기.
            wordlength = STR_Length(word);

            //[색동문자 설정]
            //{
                //문자 : 보라색.
                //바탕 : 기본.
                //형식 : 굵게.

                //[일반 문자] 로 설정한다.
                _wordconfig[_wordconfig_count].index       = wordindex;
                _wordconfig[_wordconfig_count].length      = wordlength;
                _wordconfig[_wordconfig_count].front_color = 0x8000ff;//IDE_COLOR_1;//0xff8000;
                _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;    //보라색.
                _wordconfig[_wordconfig_count].transparent = true;
                _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_bold;
                _wordconfig_count++;

            //}

            //다음 문자의 시작 위치 계산.
            wordindex += wordlength;

          }
          else if(word[0] == '$')
          {
            //[행번호] 인 경우.

            //길이 얻기.
            wordlength = STR_Length(word);

            //[색동문자 설정]
            //{
                //문자 : 갈색.
                //바탕 : 기본.
                //형식 : 기본.

                //[일반 문자] 로 설정한다.
                _wordconfig[_wordconfig_count].index       = wordindex;
                _wordconfig[_wordconfig_count].length      = wordlength;
                //[2011.06.06.월][수정!!!]
                //다른 문장의 시인성을 높이기 위하여 [은색] 으로 처리한다.
                _wordconfig[_wordconfig_count].front_color = clSilver;//clGray;
                _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
                _wordconfig[_wordconfig_count].transparent = true;
                _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;
                _wordconfig_count++;

            //}

            //다음 문자의 시작 위치 계산.
            wordindex += wordlength;

          }
          else if(STR_WordLastChar(word) == ':')
          {
            //[일반라벨] 인 경우.

            //길이 얻기.
            wordlength = STR_Length(word);

            //[색동문자 설정]
            //{
                //문자 : 회색.
                //바탕 : 기본.
                //형식 : 굵게.

                //[일반 문자] 로 설정한다.
                _wordconfig[_wordconfig_count].index       = wordindex;
                _wordconfig[_wordconfig_count].length      = wordlength;
                _wordconfig[_wordconfig_count].front_color = clGreen;
                _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
                _wordconfig[_wordconfig_count].transparent = true;
                _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;
                _wordconfig_count++;

            //}

            //다음 문자의 시작 위치 계산.
            wordindex += wordlength;

          }
          else if((STR_Match(word, "jump"))  || (STR_Match(word, "fncall")) || (STR_Match(word, "fnstart")) ||
                  (STR_Match(word, "fnend")) || (STR_Match(word, "copy"))   || (STR_Match(word, "conjt"))   ||
                  (STR_Match(word, "conjf")) || (STR_Match(word, "push"))   || (STR_Match(word, "pop"))     ||
                  (STR_Match(word, "mpush")) || (STR_Match(word, "mpop"))   || (STR_Match(word, "tstart"))  ||
                  (STR_Match(word, "tend")))
          {
            //[명령어] 인 경우.

            //길이 얻기.
            wordlength = STR_Length(word);

            //[색동문자 설정]
            //{
                //문자 : 기본 문자색(검정).
                //바탕 : 기본.
                //형식 : 굵게.

                //[일반 문자] 로 설정한다.
                _wordconfig[_wordconfig_count].index       = wordindex;
                _wordconfig[_wordconfig_count].length      = wordlength;
                _wordconfig[_wordconfig_count].front_color = IDE_COLOR_1;
                _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
                _wordconfig[_wordconfig_count].transparent = true;
                _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_bold;
                _wordconfig_count++;

            //}

            //다음 문자의 시작 위치 계산.
            wordindex += wordlength;

          }
          else if((STR_Match(word, "[]"))  || (STR_Match(word, "->"))  || (STR_Match(word, "."))   ||
                  (STR_Match(word, "!/"))  || (STR_Match(word, "~/"))  || (STR_Match(word, "++"))  ||
                  (STR_Match(word, "--"))  || (STR_Match(word, "-/"))  || (STR_Match(word, "*/"))  ||
                  (STR_Match(word, "&/"))  || (STR_Match(word, "*"))   || (STR_Match(word, "/"))   ||
                  (STR_Match(word, "%"))   || (STR_Match(word, "+"))   || (STR_Match(word, "+*"))  ||
                  (STR_Match(word, "-"))   || (STR_Match(word, "-*"))  || (STR_Match(word, "<<"))  ||
                  (STR_Match(word, ">>"))  || (STR_Match(word, "<"))   || (STR_Match(word, "<="))  ||
                  (STR_Match(word, ">"))   || (STR_Match(word, ">="))  || (STR_Match(word, "=="))  ||
                  (STR_Match(word, "!="))  || (STR_Match(word, "&"))   || (STR_Match(word, "^"))   ||
                  (STR_Match(word, "|"))   || (STR_Match(word, "&&"))  || (STR_Match(word, "||"))  ||
                  (STR_Match(word, "="))   || (STR_Match(word, "+="))  || (STR_Match(word, "+=*")) ||
                  (STR_Match(word, "-="))  || (STR_Match(word, "-=*")) || (STR_Match(word, "*="))  ||
                  (STR_Match(word, "/="))  || (STR_Match(word, "%="))  || (STR_Match(word, "&="))  ||
                  (STR_Match(word, "^="))  || (STR_Match(word, "|="))  || (STR_Match(word, "<<=")) ||
                  (STR_Match(word, ">>=")))
          {
            //[연산자] 인 경우.

            //길이 얻기.
            wordlength = STR_Length(word);

            //[색동문자 설정]
            //{
                //문자 : 청색.
                //바탕 : 기본.
                //형식 : 굵게.

                //[일반 문자] 로 설정한다.
                _wordconfig[_wordconfig_count].index       = wordindex;
                _wordconfig[_wordconfig_count].length      = wordlength;
                _wordconfig[_wordconfig_count].front_color = clBlue;
                _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
                _wordconfig[_wordconfig_count].transparent = true;
                _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_bold;
                _wordconfig_count++;

            //}

            //다음 문자의 시작 위치 계산.
            wordindex += wordlength;

          }
          else
          {
            //이 경우는 [문자열 영역] 사이에 있는 번역된 [문자열 코드] 일수 밖에는 없다.

            //길이 얻기.
            wordlength = STR_Length(word);

            //[색동문자 설정]
            //{
                //문자 : 청색.
                //바탕 : 기본.
                //형식 : 굵게.

                //[일반 문자] 로 설정한다.
                _wordconfig[_wordconfig_count].index       = wordindex;
                _wordconfig[_wordconfig_count].length      = wordlength;
                _wordconfig[_wordconfig_count].front_color = clRed;
                _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
                _wordconfig[_wordconfig_count].transparent = true;
                _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;
                _wordconfig_count++;

            //}

            //다음 문자의 시작 위치 계산.
            wordindex += wordlength;

          }

      //}

      //[행의 나머지 처리]
      //{
          //행의 나머지문자열은 일반 속성으로 일괄 설정한다.
          //현재 마지막 단어 다음의 [공백] 위치부터 이 행의 끝 까지가 된다.

          //현재 행의 문자열 길이를 구한다.
          wordlength = lineEndIndex - wordindex + 1;

          //[색동문자 설정]
          //{
              //[일반 문자] 로 설정한다.
              _wordconfig[_wordconfig_count].index       = wordindex;
              _wordconfig[_wordconfig_count].length      = wordlength;
              _wordconfig[_wordconfig_count].front_color = IDE_COLOR_1;
              _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
              _wordconfig[_wordconfig_count].transparent = true;
              _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;
              _wordconfig_count++;

          //}

      //}

  //}

  return;

}

void __fastcall Teditor_edit_Form::_MoonjaConfig_LineGet_Gcsm(int   pLineStartIndex,
                                                              int  *rLineEndIndex)
{
  //[2009.04.01.수][생성!!!]{-------------------------------------------------
  //<*.gcsm> 문서의 [색동문자] 기능을 처리한다.
  //
  //<*.gcsm> 문서는 <*.c> 와 <*.gasm> 이 합성된 형태이므로 먼저 행을 검사하고
  //둥줄 어느 문서형식인지 확인후 해당 함수를 호출하여 처리한다.
  //}-------------------------------------------------------------------------

  //[형식 구분]
  //{
      //[방법]{---------------------------------------------------------------------
      //<*.c> 인지 아닌지 확인하는 것이 더 간단하다.
      //<*.gasm> 은 반드시 [주소] 또는 [주소 없음 문자열] 둘중 하나도 시작하므로
      //간단하게 확인 가능하다.
      //<*.c> 문서는 이 공간에 그냥 해당 길이의 공백만 존재한다.
      //즉, 첫 [16 Byte] 문자열이 전체가 공백이라면 이 행은 <*.c> 문서의 행이 된다.
      //}---------------------------------------------------------------------------

      //행의 젓문자가 [공백] 이라면 <*.c> 문서의 행이 된다.
      if(_editbuf[pLineStartIndex] == ' ')
      {
        //<*.c> 문서의 합성 행이 된다.
        _MoonjaConfig_LineGet_C(pLineStartIndex, rLineEndIndex);

      }
      else
      {
        //<*.gasm> 문서의 합성 행이 된다.
        _MoonjaConfig_LineGet_Gasm(pLineStartIndex, rLineEndIndex);

      }

  //}

  return;

}

void __fastcall Teditor_edit_Form::_MoonjaConfig_LineGet_Obj(int   pLineStartIndex,
                                                             int  *rLineEndIndex)
{
  //[2011.05.27.금][생성!!!]{--------------------------------
  //<*.gobj>, <*.glib> 문서의 [색동문자] 처리를 수행한다.
  //
  //[gobj/glib 문서 내용]------------------------------------
  //
  //:main:
  //2e :main: 01600c
  //37 016002
  //2d :_Pwm_생성_:
  //
  //의 형식으로 돼 있으며,
  //[첫단어] 는 반드시 [함수라벨] 이나 [명령어] 가 된다.
  //
  //[첫단어]-------------------------------------------------
  //
  //- <함수라벨> : [함수라벨] 로 적용한다.
  //- <XX>       : 1 바이트 명령이므로 [명령] 으로 처리한다.
  //
  //[나머지]
  // 일반 문서로 처리.
  //}--------------------------------------------------------

  //[VAR]
  //{
      char   word[OPT_str_default_size*10];
      int    wordindex;
      int    wordlength;
      int    lineEndIndex;

  //}

  //[초기화]
  //{
      _wordconfig_count = 0;

  //}

  //[문법강조처리]
  //{
      //[!]{--------------------------------------------------------------------------
      //이 경우는 [함수라벨], [명령어 코드] 만 처리하면 된다.
      //<*.c> 와는 달리 정해진 형식으로 문서가 만들어져 있으므로 직접 단어를 추출하여
      //간단하게 처리한다.
      //"[첫단어] ..." 의 형식으로 모든 처리대상 단어는 이 [첫단어] 위치에 있다.
      //}-----------------------------------------------------------------------------

      //이 행의 끝위치 구하기.
      STR_Get_ThisLineEndIndex(_editbuf, pLineStartIndex, &lineEndIndex);

      //[행 끝 위치 반환][2009.05.09.토][추가!!!]{-------------------
      if(rLineEndIndex != NULL) { (*rLineEndIndex) = lineEndIndex; }
      //}------------------------------------------------------------

      //[처리할 문서가 있는가?]
      //{
          //[!]{---------------------------------------------------------------------
          //처리할 문자열이 없으므로 처리하지 않고 종료한다.
          //
          //[주의!!!]----------------------------------------------------------------
          //이것을 처리하지 않으면 _wordconfig_count 이 0 이 아닌것으로 되므로
          //이 함수를 사용하는 함수에서 계속 처리를 시도하는 [무한반복] 상태가 된다.
          //}------------------------------------------------------------------------

          if(pLineStartIndex >= lineEndIndex) { _wordconfig_count = 0; return; }

      //}

      //[!]{------------------------------------
      //단순하게 순서대로 읽어서 처리하면 된다.
      //}---------------------------------------

      //처음 문자 위치 계산.
      wordindex = pLineStartIndex;

      //[첫단어 구분 처리]
      //{
          //[!]{-------------------------------------------------------------------------
          //[주소] 다음의 [첫 단어] 만 처리 대상이 되므로 이의 종류를 구분하여 처리한다.
          //}----------------------------------------------------------------------------

          //[단어 추출]
          //{
              STR_GetLineWordBuf(_editbuf, wordindex, 0, &wordindex, word);

          //}


          //[문자열 코드 인가?]
          //{
              //[2011.06.02.목][추가!!!]{----------------------------------------------------------
              //<*.ogj> 계열 문서에는 [문자열] 의 경우도 있을수 있으므로 이것을 구분하여 처리한다.
              //
              //1)문자열 코드는 반드시 끝에 "00" 이 붙어 있다.
              //2)첫단어는 모두 [명령어] 이므로 끝에 "00" 이 붙을수 없다.
              //따라서, 첫단어뒤에 "00" 이 붙어 있다면 [문자열] 로 본다.
              //}----------------------------------------------------------------------------------

              wordlength = STR_Length(word);

              //[문자열 코드 검사]
              //{
                  //NULL 문자열 이라도 최소한 "00" 는 붙어 있으므로 최소 2문자는 되어야 한다.
                  if(wordlength < 2) goto lbNoStrCode;

                  //첫단어 끝에 "00" 이 붙어 있는지만 검사한다.
                  if(!((word[wordlength - 2] == '0') && (word[wordlength - 1] == '0'))) goto lbNoStrCode;

              //}

              //현재 행의 문자열 길이를 구한다.
              wordlength = lineEndIndex - wordindex + 1;

              //[색동문자 설정]
              //{
                  //[일반 문자] 로 설정한다.
                  _wordconfig[_wordconfig_count].index       = wordindex;
                  _wordconfig[_wordconfig_count].length      = wordlength;
                  _wordconfig[_wordconfig_count].front_color = clGray;//IDE_COLOR_1;
                  _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
                  _wordconfig[_wordconfig_count].transparent = true;
                  _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;
                  _wordconfig_count++;

              //}

              //문자열은 전체 행에 1개 단어 형태로 존재하므로 더이상 처리하지 않고 종료한다.
              return;

          //}


          lbNoStrCode:

          //정해진 문자만 검색하는것으로 간단하게 종류를 구분할수 있다.
          if     (word[0] == ':')
          {
            //[함수라벨] 인 경우.

            //길이 얻기.
            wordlength = STR_Length(word);

            //[색동문자 설정]
            //{
                //문자 : 보라색.
                //바탕 : 기본.
                //형식 : 굵게.

                //[일반 문자] 로 설정한다.
                _wordconfig[_wordconfig_count].index       = wordindex;
                _wordconfig[_wordconfig_count].length      = wordlength;
                _wordconfig[_wordconfig_count].front_color = 0x8000ff;//IDE_COLOR_1;//0xff8000;
                _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;    //보라색.
                _wordconfig[_wordconfig_count].transparent = true;
                _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_bold;
                _wordconfig_count++;

            //}

            //다음 문자의 시작 위치 계산.
            wordindex += wordlength;

          }
          else
          {
            //[!]{--------------------------------------------------------
            //[명령어] 인 경우.
            //
            //[2011.05.28.토][수정!!!]------------------------------------
            //중요한 [함수 관련 명령] 과 일만 병령을 구분하여 처리한다.
            //<fncall:0x2d>, <fnstart:0x2e>, <fnend:0x2f> 3지가 해당된다.
            //}-----------------------------------------------------------

            if((STR_Match(word, "2d"))     || (STR_Match(word, "2e"))      || (STR_Match(word, "2f")) ||
               (STR_Match(word, "fncall")) || (STR_Match(word, "fnstart")) || (STR_Match(word, "fnend")))
            {
              //[함수관련명령] 인 경우다.

              //길이 얻기.
              wordlength = STR_Length(word);

              //[색동문자 설정]
              //{
                  //[!]{----------------------
                  //문자 : 명령어색.
                  //바탕 : 기본.
                  //형식 : 굵게.
                  //}-------------------------

                  //[일반 문자] 로 설정한다.
                  _wordconfig[_wordconfig_count].index       = wordindex;
                  _wordconfig[_wordconfig_count].length      = wordlength;
                  _wordconfig[_wordconfig_count].front_color = clBlue;
                  _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
                  _wordconfig[_wordconfig_count].transparent = true;
                  _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_bold;
                  _wordconfig_count++;

              //}

              //다음 문자의 시작 위치 계산.
              wordindex += wordlength;

            }
            else
            {
              //[일반명령] 인 경우다.

              //길이 얻기.
              wordlength = STR_Length(word);

              //[색동문자 설정]
              //{
                  //[!]{----------------------
                  //문자 : 기본 문자색(검정).
                  //바탕 : 기본.
                  //형식 : 굵게.
                  //}-------------------------

                  //[일반 문자] 로 설정한다.
                  _wordconfig[_wordconfig_count].index       = wordindex;
                  _wordconfig[_wordconfig_count].length      = wordlength;
                  _wordconfig[_wordconfig_count].front_color = IDE_COLOR_1;
                  _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
                  _wordconfig[_wordconfig_count].transparent = true;
                  _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_bold;
                  _wordconfig_count++;

              //}

              //다음 문자의 시작 위치 계산.
              wordindex += wordlength;

            }


          }

      //}

      //[행의 나머지 처리]
      //{
          //[!]{------------------------------------------------------------------
          //첫 단어가 <fncall:2d> 인 경우는 [두번째] 단어가 [사용함수라벨] 이므로
          //이 [사용함수라벨] 을 [색동문자] 로 적용한다.
          //
          //행의 나머지문자열은 일반 속성으로 일괄 설정한다.
          //현재 마지막 단어 다음의 [공백] 위치부터 이 행의 끝 까지가 된다.
          //}---------------------------------------------------------------------

          if     (STR_Match_NoCase(word, "2d") || STR_Match_NoCase(word, "fncall"))
          {
            //[!]{-------------------------------------------------------------------------
            //{ 2d :_Pwm_생성_: } 의 경우로 두번째 단어가 끝이고, [사용함수라벨] 이 된다.
            //[사용함수라벨] 은 [함수라벨] 과 같은 색으로 하고 문자는 일반문자로 처리한다.
            //}----------------------------------------------------------------------------

            //현재 행의 문자열 길이를 구한다.
            wordlength = lineEndIndex - wordindex + 1;

            //[색동문자 설정]
            //{
                //[일반 문자] 로 설정한다.
                _wordconfig[_wordconfig_count].index       = wordindex;
                _wordconfig[_wordconfig_count].length      = wordlength;
                _wordconfig[_wordconfig_count].front_color = 0x8000ff;
                _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
                _wordconfig[_wordconfig_count].transparent = true;
                _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;
                _wordconfig_count++;

            //}

          }
          else if(STR_Match_NoCase(word, "2e") || STR_Match_NoCase(word, "fnstart"))
          {
            //[2011.05.28.토][추가!!!]{----------------------------------------------------
            //{ 2e :main: 016000 } 의 경우로 두번째 단어가 끝이고, [사용함수라벨] 이 된다.
            //<fnstart:0x2e> 로 중요한 행이므로 모두 명령어 행으로 처리한다.
            //}----------------------------------------------------------------------------

            //현재 행의 문자열 길이를 구한다.
            wordlength = lineEndIndex - wordindex + 1;

            //[색동문자 설정]
            //{
                //[일반 문자] 로 설정한다.
                _wordconfig[_wordconfig_count].index       = wordindex;
                _wordconfig[_wordconfig_count].length      = wordlength;
                _wordconfig[_wordconfig_count].front_color = clBlue;
                _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
                _wordconfig[_wordconfig_count].transparent = true;
                _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;
                _wordconfig_count++;

            //}

          }
          else
          {
            //현재 행의 문자열 길이를 구한다.
            wordlength = lineEndIndex - wordindex + 1;

            //[색동문자 설정]
            //{
                //[일반 문자] 로 설정한다.
                _wordconfig[_wordconfig_count].index       = wordindex;
                _wordconfig[_wordconfig_count].length      = wordlength;
                _wordconfig[_wordconfig_count].front_color = IDE_COLOR_1;
                _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
                _wordconfig[_wordconfig_count].transparent = true;
                _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;
                _wordconfig_count++;

            //}

          }

      //}

  //}

  return;

}

void __fastcall Teditor_edit_Form::_MoonjaConfig_LineGet_Gtmp(int   pLineStartIndex,
                                                              int  *rLineEndIndex)
{
  //[2011.06.06.월][생성!!!]{------------------------------------------------------------------
  //<*.gtmp> 문서의 [색동문자] 처리를 수행한다.
  //
  //[종류 구분]
  //
  //1) $행번호               : 행번호 적용.
  //
  //2) [명령어/연산자] ...   : 명령어/연산자 적용, 나머지는 일반 문자.
  //
  //3) #TEMP{ ...            : 라벨색 + 굵게, 나머지는 일반문자.
  //   #TEMP}
  //
  //4) "문자열..."           : 행 전체를 문자열 적용.
  //
  //5) FD.x.{: ...           : 함수라벨 적용, 나머지는 일반 문자열.
  //
  //6) FD.x.}:               : 함수라벨 적용, 단, 일반굵기 적용.
  //
  //7) 일반라벨:             : 일반라벨 적용.
  //
  //[명령행] 이 가장 일반적이므로 다른 것에 해당하지 않는 경우는 무조건 [명령행] 으로 처리한다.
  //}-------------------------------------------------------------------------------------------

  //[VAR]
  //{
      //내부에 문자열 처리부가 있으므로 이렇게 길게 잡아야 한다.
      char   word[OPT_str_default_size*10];
      int    wordindex;
      int    wordlength;
      int    lineEndIndex;

  //}

  //[초기화]
  //{
      _wordconfig_count = 0;

  //}

  //[문법강조처리]
  //{
      //[!]{----------------------------------------
      //[첫단어] 만 검사하면 모든 정보를 알수 있다.
      //}-------------------------------------------

      //이 행의 끝위치 구하기.
      STR_Get_ThisLineEndIndex(_editbuf, pLineStartIndex, &lineEndIndex);

      //[행 끝 위치 반환]{-------------------------------------------
      if(rLineEndIndex != NULL) { (*rLineEndIndex) = lineEndIndex; }
      //}------------------------------------------------------------

      //[처리할 문서가 있는가?]
      //{
          //[!]{---------------------------------------------------------------------
          //처리할 문자열이 없으므로 처리하지 않고 종료한다.
          //
          //[주의!!!]----------------------------------------------------------------
          //이것을 처리하지 않으면 _wordconfig_count 이 0 이 아닌것으로 되므로
          //이 함수를 사용하는 함수에서 계속 처리를 시도하는 [무한반복] 상태가 된다.
          //}------------------------------------------------------------------------

          if(pLineStartIndex >= lineEndIndex) { _wordconfig_count = 0; return; }

      //}

      //[초기화]
      //{
          //처음 문자 위치 계산.
          wordindex = pLineStartIndex;

      //}

      //[첫번째 단어 구분 처리]
      //{
          //[!]{----------------------------------------------------
          //[첫번째 단어] 만 검사하면 모든 것을 구분 처리할수 있다.
          //}-------------------------------------------------------

          //[문자열 인가?]
          //{
              //[!]{----------------------------------------------------------
              //[문자열] 의 경우는 상당히 길수 있으므로 별도로 먼저 처리한다.
              //{ "문자열" } 의 형식으로 한개 행 전체를 차지한다.
              //}-------------------------------------------------------------

              //행의 [첫문자] 가 <"> 이라면 이 행은 [문자열] 행이다.
              if(_editbuf[wordindex] == '\"')
              {
                //[!]{--------------------------------------
                //이 행의 끝까지 전부 [문자열] 로 적용한다.
                //}-----------------------------------------

                //현재 행의 문자열 길이를 구한다.
                wordlength = lineEndIndex - wordindex + 1;

                //[색동문자 설정]
                //{
                    //[일반 문자] 로 설정한다.
                    _wordconfig[_wordconfig_count].index       = wordindex;
                    _wordconfig[_wordconfig_count].length      = wordlength;
                    _wordconfig[_wordconfig_count].front_color = clRed;
                    _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
                    _wordconfig[_wordconfig_count].transparent = true;
                    _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;
                    _wordconfig_count++;

                //}

                //더이상 처리하지 않고 종료한다.
                return;

              }

          //}

          lbNoString:

          //[단어 추출]
          //{
              //[!]{---------------------------------------------------------
              //여기서 부터는 [첫단어] 를 추출해야 쉽게 처리 가능하고,
              //[문자열] 은 위에서 이미 처리되었으므로 [첫단어] 를 추출한다.
              //}------------------------------------------------------------

              STR_GetLineWordBuf(_editbuf, wordindex, 0, NULL, word);

          //}

          if     ((word[0] == 'F') && (word[1] == 'D'))

          {
            //[!]{---------------------------------
            //[함수라벨] 인 경우.
            //
            //{ FD.x.{: ... } 함수시작라벨 이거나.
            //
            //{ FD.x.}:     } 함수끝라벨이다.
            //}------------------------------------

            //[단어] 끝 이전 문자가 "{" 가 되어야 [함수시작라벨] 이 된다.
            if     (word[STR_Length(word) - 2] == '{')
            {
              //[!]{-----------------------------------------------------
              //{ FD.x.{: ... } 함수시작라벨 인 경우.
              //단, { FD.x.STR.{: } 인 경우는 일반 라벨로 처리해야 한다.
              //}--------------------------------------------------------

              if(word[STR_Length(word) - 4] != 'R')
              {
                //[함수라벨인 경우]

                //길이 얻기.
                wordlength = STR_Length(word);

                //[색동문자 설정]
                //{
                    _wordconfig[_wordconfig_count].index       = wordindex;
                    _wordconfig[_wordconfig_count].length      = wordlength;
                    _wordconfig[_wordconfig_count].front_color = 0x8000ff;//IDE_COLOR_1;//0xff8000;
                    _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;    //보라색.
                    _wordconfig[_wordconfig_count].transparent = true;
                    _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_bold;
                    _wordconfig_count++;

                //}

                //다음 문자의 시작 위치 계산.
                wordindex += wordlength;

              }
              else
              {
                //[!]{--------------------------------------------------
                //{ FD.x.STR.{: } 인 경우이므로 [일반라벨] 로 처리한다.
                //}-----------------------------------------------------

                //길이 얻기.
                wordlength = STR_Length(word);

                //[색동문자 설정]
                //{
                    _wordconfig[_wordconfig_count].index       = wordindex;
                    _wordconfig[_wordconfig_count].length      = wordlength;
                    _wordconfig[_wordconfig_count].front_color = clGreen;
                    _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
                    _wordconfig[_wordconfig_count].transparent = true;
                    _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;
                    _wordconfig_count++;

                //}

                //다음 문자의 시작 위치 계산.
                wordindex += wordlength;

              }

            }
            else if(word[STR_Length(word) - 2] == '}')
            {
              //[!]{--------------------------------------------------
              //{ FD.x.}: } 함수끝라벨 인 경우.
              //단, { FD.x.STR.}: } 인 경우는 [일반라벨] 로 처리한다.
              //}-----------------------------------------------------

              if(word[STR_Length(word) - 4] != 'R')
              {
                //길이 얻기.
                wordlength = STR_Length(word);

                //[색동문자 설정]
                //{
                    _wordconfig[_wordconfig_count].index       = wordindex;
                    _wordconfig[_wordconfig_count].length      = wordlength;
                    _wordconfig[_wordconfig_count].front_color = 0x8000ff;//IDE_COLOR_1;//0xff8000;
                    _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;    //보라색.
                    _wordconfig[_wordconfig_count].transparent = true;
                    _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;
                    _wordconfig_count++;

                //}

                //다음 문자의 시작 위치 계산.
                wordindex += wordlength;

              }

              else
              {
                //[!]{--------------------------------------------------
                //{ FD.x.STR.}: } 인 경우이므로 [일반라벨] 로 처리한다.
                //}-----------------------------------------------------

                //길이 얻기.
                wordlength = STR_Length(word);

                //[색동문자 설정]
                //{
                    _wordconfig[_wordconfig_count].index       = wordindex;
                    _wordconfig[_wordconfig_count].length      = wordlength;
                    _wordconfig[_wordconfig_count].front_color = clGreen;
                    _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
                    _wordconfig[_wordconfig_count].transparent = true;
                    _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;
                    _wordconfig_count++;

                //}

                //다음 문자의 시작 위치 계산.
                wordindex += wordlength;

              }

            }

          }
          else if(word[0] == '$')
          {
            //[!]{--------------
            //[행번호] 인 경우.
            //
            //{ $행번호 } 형식.
            //}-----------------

            //길이 얻기.
            wordlength = STR_Length(word);

            //[색동문자 설정]
            //{
                //[일반 문자] 로 설정한다.
                _wordconfig[_wordconfig_count].index       = wordindex;
                _wordconfig[_wordconfig_count].length      = wordlength;
                _wordconfig[_wordconfig_count].front_color = clSilver;//clGray;
                _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
                _wordconfig[_wordconfig_count].transparent = true;
                _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;
                _wordconfig_count++;

            //}

            //다음 문자의 시작 위치 계산.
            wordindex += wordlength;

          }
          else if(STR_WordLastChar(word) == ':')
          {
            //[!]{------------------------
            //[일반라벨] 인 경우.
            //
            // { 일반라벨: } 형식의 경우.
            //}---------------------------

            //길이 얻기.
            wordlength = STR_Length(word);

            //[색동문자 설정]
            //{
                _wordconfig[_wordconfig_count].index       = wordindex;
                _wordconfig[_wordconfig_count].length      = wordlength;
                _wordconfig[_wordconfig_count].front_color = clGreen;
                _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
                _wordconfig[_wordconfig_count].transparent = true;
                _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;
                _wordconfig_count++;

            //}

            //다음 문자의 시작 위치 계산.
            wordindex += wordlength;

          }
          else if(STR_Match(word, "#TEMP{") || STR_Match(word, "#TEMP}"))
          {
            //[!]{--------------------
            //{ #TEMP{ ... }
            //{ #TEMP}     } 인 경우.
            //}-----------------------

            //길이 얻기.
            wordlength = STR_Length(word);

            //[색동문자 설정]
            //{
                //[일반 문자] 로 설정한다.
                _wordconfig[_wordconfig_count].index       = wordindex;
                _wordconfig[_wordconfig_count].length      = wordlength;
                _wordconfig[_wordconfig_count].front_color = 0x80ff;//clGreen;
                _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
                _wordconfig[_wordconfig_count].transparent = true;
                _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;
                _wordconfig_count++;

            //}

            //다음 문자의 시작 위치 계산.
            wordindex += wordlength;

          }
          else if((STR_Match(word, "jump"))  || (STR_Match(word, "fncall")) || (STR_Match(word, "fnstart")) ||
                  (STR_Match(word, "fnend")) || (STR_Match(word, "copy"))   || (STR_Match(word, "conjt"))   ||
                  (STR_Match(word, "conjf")) || (STR_Match(word, "push"))   || (STR_Match(word, "pop"))     ||
                  (STR_Match(word, "mpush")) || (STR_Match(word, "mpop"))   || (STR_Match(word, "tstart"))  ||
                  (STR_Match(word, "tend")))
          {
            //[명령어] 인 경우.

            //길이 얻기.
            wordlength = STR_Length(word);

            //[색동문자 설정]
            //{
                //문자 : 기본 문자색(검정).
                //바탕 : 기본.
                //형식 : 굵게.

                //[일반 문자] 로 설정한다.
                _wordconfig[_wordconfig_count].index       = wordindex;
                _wordconfig[_wordconfig_count].length      = wordlength;
                _wordconfig[_wordconfig_count].front_color = IDE_COLOR_1;
                _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
                _wordconfig[_wordconfig_count].transparent = true;
                _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_bold;
                _wordconfig_count++;

            //}

            //다음 문자의 시작 위치 계산.
            wordindex += wordlength;

          }
          else if((STR_Match(word, "[]"))  || (STR_Match(word, "->"))  || (STR_Match(word, "."))   ||
                  (STR_Match(word, "!/"))  || (STR_Match(word, "~/"))  || (STR_Match(word, "++"))  ||
                  (STR_Match(word, "--"))  || (STR_Match(word, "-/"))  || (STR_Match(word, "*/"))  ||
                  (STR_Match(word, "&/"))  || (STR_Match(word, "*"))   || (STR_Match(word, "/"))   ||
                  (STR_Match(word, "%"))   || (STR_Match(word, "+"))   || (STR_Match(word, "+*"))  ||
                  (STR_Match(word, "-"))   || (STR_Match(word, "-*"))  || (STR_Match(word, "<<"))  ||
                  (STR_Match(word, ">>"))  || (STR_Match(word, "<"))   || (STR_Match(word, "<="))  ||
                  (STR_Match(word, ">"))   || (STR_Match(word, ">="))  || (STR_Match(word, "=="))  ||
                  (STR_Match(word, "!="))  || (STR_Match(word, "&"))   || (STR_Match(word, "^"))   ||
                  (STR_Match(word, "|"))   || (STR_Match(word, "&&"))  || (STR_Match(word, "||"))  ||
                  (STR_Match(word, "="))   || (STR_Match(word, "+="))  || (STR_Match(word, "+=*")) ||
                  (STR_Match(word, "-="))  || (STR_Match(word, "-=*")) || (STR_Match(word, "*="))  ||
                  (STR_Match(word, "/="))  || (STR_Match(word, "%="))  || (STR_Match(word, "&="))  ||
                  (STR_Match(word, "^="))  || (STR_Match(word, "|="))  || (STR_Match(word, "<<=")) ||
                  (STR_Match(word, ">>=")))
          {
            //[연산자] 인 경우.

            //길이 얻기.
            wordlength = STR_Length(word);

            //[색동문자 설정]
            //{
                //문자 : 청색.
                //바탕 : 기본.
                //형식 : 굵게.

                //[일반 문자] 로 설정한다.
                _wordconfig[_wordconfig_count].index       = wordindex;
                _wordconfig[_wordconfig_count].length      = wordlength;
                _wordconfig[_wordconfig_count].front_color = clBlue;
                _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
                _wordconfig[_wordconfig_count].transparent = true;
                _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_bold;
                _wordconfig_count++;

            //}

            //다음 문자의 시작 위치 계산.
            wordindex += wordlength;

          }

      //}

      //[행의 나머지 처리]
      //{
          //[!]{------------------------------------------------------------
          //행의 나머지문자열은 일반 속성으로 일괄 설정한다.
          //현재 마지막 단어 다음의 [공백] 위치부터 이 행의 끝 까지가 된다.
          //}---------------------------------------------------------------

          //현재 행의 문자열 길이를 구한다.
          wordlength = lineEndIndex - wordindex + 1;

          //[색동문자 설정]
          //{
              //[일반 문자] 로 설정한다.
              _wordconfig[_wordconfig_count].index       = wordindex;
              _wordconfig[_wordconfig_count].length      = wordlength;
              _wordconfig[_wordconfig_count].front_color = IDE_COLOR_1;
              _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
              _wordconfig[_wordconfig_count].transparent = true;
              _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;
              _wordconfig_count++;

          //}

      //}

  //}

  return;

}

void __fastcall Teditor_edit_Form::_MoonjaConfig_LineGet_Default(int   pLineStartIndex,
                                                                 int  *rLineEndIndex)
{
  //[2009.04.01.수][생성!!!]{----------------------------------
  //<*.*> 등 [색동문자] 가 적용되는 않는 일반 문서를 처리한다.
  //}----------------------------------------------------------

  //[VAR]
  //{
      int    wordlength;

      //[2009.04.01.수][추가!!!]
      int    lineEndIndex;

  //}

  //[초기화]
  //{
      _wordconfig_count = 0;

  //}

  //[문법강조처리]
  //{
      //[2009.04.01.수][추가!!!]{-----------------------------------------------------------
      //그냥 현재 행 전체를 일반 속성으로 설정하면 된다.
      //[단어] 를 구분하는 아무 의미가 없으므로.
      //
      //[참고]------------------------------------------------------------------------------
      //처리를 단순화 함으로써 연동에 차이가 발생하여 _EDITBUF_STRING_Out() 함수를
      //수정 보완 하였다. 오히려 이전에 놓쳤던 문제를 발견하고 보완 한것이므로 잘된 것이다.
      //}-----------------------------------------------------------------------------------

      //이 행의 끝위치 구하기.
      STR_Get_ThisLineEndIndex(_editbuf, pLineStartIndex, &lineEndIndex);

      //[행 끝 위치 반환][2009.05.09.토][추가!!!]{-------------------
      if(rLineEndIndex != NULL) { (*rLineEndIndex) = lineEndIndex; }
      //}------------------------------------------------------------

      //[처리할 문서가 있는가?]
      //{
          //[!]{---------------------------------------------------------------------
          //처리할 문자열이 없으므로 처리하지 않고 종료한다.
          //
          //[주의!!!]----------------------------------------------------------------
          //이것을 처리하지 않으면 _wordconfig_count 이 0 이 아닌것으로 되므로
          //이 함수를 사용하는 함수에서 계속 처리를 시도하는 [무한반복] 상태가 된다.
          //}------------------------------------------------------------------------

          if(pLineStartIndex >= lineEndIndex) { _wordconfig_count = 0; return; }

      //}

      //현재 행의 문자열 길이를 구한다.
      wordlength = lineEndIndex - pLineStartIndex + 1;

      //[색동문자 설정]
      //{
          //[일반 문자] 로 설정한다.
          _wordconfig[_wordconfig_count].index       = pLineStartIndex;
          _wordconfig[_wordconfig_count].length      = wordlength;
          _wordconfig[_wordconfig_count].front_color = IDE_COLOR_1;
          _wordconfig[_wordconfig_count].back_color  = IDE_COLOR_2;
          _wordconfig[_wordconfig_count].transparent = true;
          _wordconfig[_wordconfig_count].style       = d_FONTSTYLE_default;
          _wordconfig_count++;

      //}

  //}

  return;

}



//------------------------------------------------------------------------------
//[/* ... */ 주석문 관련]-------------------------------------------------------
//------------------------------------------------------------------------------

bool __fastcall Teditor_edit_Form::_CommentBlock_Info(//부분처리인 경우는 <true>.
                                                      bool  pPartInfo)
{
  //[2005.04.21.목][작성!!!]{--------------------------------------------------------------
  //<GetNextWord()> 함수를 바탕으로 {/* ... */} [주석문] 을 위하여 해당 영역의 정보를
  //수집하는 것만 수행한다.
  //
  //이는 문서 [저장소] 를 직접 처리 대상으로 하고 현재 편집기상의 문서 자체만을
  //대상으로 하며 /* ... */ 는 여러개의 영역을 가질수 있으므로 정보는 여러개가 되고
  //현재 보이는 영역과 겹치는 것 까지만 처리하면 된다.
  //
  //처리속도가 생명이고 오직 {/* ... */} 주석영역을 검출하기만 하면 되므로 이에 불필요한
  //모든 부분은 다 제거한다.
  //단어반환이나 실수처리부 등은 전부 제거 한다.
  //
  // "/*" : 시작위치.
  // "*/" : 끝위치.
  //
  //[2012.05.09.수][중요수정!!!]-----------------------------------------------------------
  //[문자상수], [문자열] 의 경우는 [1개 행] 만 대상이 되고, 행이 바뀌는 경우 무효가 되므로
  //이를 반영하여 행이 바뀌는 경우는 [문자상수], [문자열] 을 해제하는 것을 추가한다.
  //당연한 것인데 이제껏 몰랐다.
  //금일 발견하고 수정한다.
  //
  //이 함수는 [색동문자] 적용때만 사용하는 것으로 [문법] 과는 무관하다.
  //
  //[2012.06.11.월][대폭수정!!!]-----------------------------------------------------------
  //[행] 이 변한것이 있다면 [전체 다시 그리기] 상태임을 반환.
  //
  //[항목수] 가 변경된 경우도 [묶음주석] 의 [추가/삭제] 와 관련이 있으므로 반드시
  //[다시 그리기] 를 하도록 [수정] 으로 반환.
  //
  //[2012.06.12.화[수정!!!]----------------------------------------------------------------
  //[문서-처음:끝] 까지 전부 수집하지 않고 [처음:보이는 영역] 까지만 수집.
  //[보이는 영역] 에서 [다시 그리기] 를 위해서만 필요한 정보이므로 [보이는 영역 다음]
  //정보는 불필요.
  //
  //다음 정보는 [줄이동] 등 보이는 영역의 수정 다음 영역으로 이동시 수시로 구한다.
  //
  //[보이는 영역 끝까지] 가 보다 우선 조건이고 [문서 끝까지] 는 다음 조건.
  //
  //[주의!!!]------------------------------------------------------------------------------
  //[문서를 처음 열때], [문서 전환시] 등에서는 항상 [한번] 은 [묶음주석] 정보를 수집하므로
  //이전 정보는 반드시 존재한다고 보고 처리한다.
  //
  //처음부터 검사하는 경우는 이전 정보와 비교 판별은 불필요 하고 항상 [수정] 으로 판별.
  //
  //[2012.06.13.수][재설계!!!]-------------------------------------------------------------
  //[묶음주석] 정보 수집/처리 방식을 완전히 [재설계].
  //
  //[보이는 영역(쪽)] [이하/초과] 인지에 따라 [부분/전체] 수집여부를 결정.
  //
  //항상 [보이는 영역:끝] 까지만 정보를 수집.
  //
  //[2012.06.19.화][수정!!!]---------------------------------------------------------------
  //}--------------------------------------------------------------------------------------


  //[처리분류!!!][2012.06.14.목][추가!!!]{**************************************
  //
  //[수정시]--------------------------------------------------------------------
  //
  // - [보이는 영역] 관련 부분만 정보 수집/수정.
  //   대부분이 여기에 해당.
  //
  //[수직 줄이동시]-------------------------------------------------------------
  //
  // - <_EDIT_V_Scroll()> 이벤트 처리 함수 부분에서 처리.
  //
  // - [쪽단위] 이하 이동시는 [부분] 정보 수집.
  //   [쪽단위] 초과 이동시는 [전체] 정보 수집.
  //
  // - [보이는 영역(쪽)] 을 건너뛰어 이동하는 경우는 [초과] 에 해당하고
  //   문서 [처음] 부터 [보이는 영역 끝]  까지 처리.
  //
  //[묶음 주석 정보] 는 계속 실시간으로 관리되고 [부분 수집] 시에는
  //[부분] 만 [수정/추가] 된다.
  //
  //[전체 수집:반드시]----------------------------------------------------------
  //
  // - [문서열기/전환/처음저장] 시는 반드시 한번은 [전체수집] 을 한다.
  //
  // - [보이는 영역(쪽)] 단위를 [초과] 이동하는 부분이 존재하는 경우.
  //   <Ctrl+End/Home> 사용시나 [수직 줄이동] 을 순간적으로 크게 이동하는 경우.
  //   [쪽] 단위 이상의 큰 문자열을 [붙이기/잘라내기] 하는 경우.
  //
  // - [붙이기/잘라내기] 는 [수정] 부분에서 먼저 [부분 수집] 으로 처리되지만
  //   [쪽] 단위를 넘는 경우 자동적으로 [수직 줄이동] 이 이루어지고 해당 이벤트
  //   처리부에서 다시 [전체수집] 을 하게 되어 언제나 정확성을 보장받는다.
  //
  //아주 특정한 조건이고 [한번] 정도 존재하므로 [편집] 에 영향이 없다.
  //
  //[구분 핵심!!!]--------------------------------------------------------------
  //
  //문서 이동량이 [보이는 영역(쪽)] 단위 [이하] 인지 [초과] 인지가 중요.
  //[그린다] 는 것은 [보이는 영역] 만 처리하므로 [보이는 영역] 이 기준이 된다.
  //
  //[보이는 영역 시작 정보]-----------------------------------------------------
  //
  //<_linetop_linenumber>, <_linetop_startindex> 가 해당.
  //
  //[보이는 영역(쪽)] 은 <키:PageUp/Down> 으로 이동하는 행수과 같다.
  //
  //}***************************************************************************


  //[VAR]
  //{
      int    index;

      char   whatIn = 0;

      char   chr = 0;

      //[2005.09.24.토][주의!!!]------------------------------------------
      //이 변수는 이 함수 안에 선언되면 함수가 호출될때마다 초기화 되므로
      //아무 의미가 없어진다. 또한 Parser() 시에 문자열의 에러 체크 등에
      //사용될수 있는 정보이므로 인수로 전달받을수 있는 PARSERINFO 안에
      //정보를 추가해 놓는다.
      // "char  what_in = 0;"
      //0 : 아무 영역도 아님.
      //c : ' ... ' 문자상수 안. 뒤의 [']  에서 영역 해제됨.
      //s : " ... " 문자열 안. 뒤의 ["]  에서 영역 해제됨.
      //r : /* ... */ 주석문 안. 뒤의 [*/] 에서 영역 해제됨.
      //h : // ...    주석문 안. 이 행의 끝까지 모두 주석문임.
      //    CRLF 로 행이 바뀌면 해제됨(CRLF 를 검사하는 부분에서 해제).
      //}-----------------------------------------------------------------

      int   infoCount;

      //현재 행번호 관리.
      int   line;

      //[2012.06.11.월][추가!!!]
      //[항목] 중 [행] 정보가 변한 것이 있는 경우는 <true>;
      bool  changed;

      //[수정] 되기전 이전 항목 정보.
      struct COMMENTBLOCK_INFO_ITEM  bfItem;

      //[검사 조건]
      //{
          //이미 수집된 정보에서 현재 검사를 시작할 항목 위치.
          int  cdItemIndex = 0;

          //검사할 시작행.
          int  cdLineS;

          //검사할 마지막 행.
          int  cdLineE;

          int  i;

      //}

  //}

  //[문서종류 구분]
  //{
      //[2009.06.03.수][추가!!!]{------------------
      //[묶음주석] 을 적용하는 문서인 경우만 처리.
      //}------------------------------------------

      if(!((_fileKind == d_Editor_FileKind_c)    ||
           (_fileKind == d_Editor_FileKind_gtxt) ||
           //[2009.06.06.토][추가!!!]
           //{/* ...*/} 주석문은 사이에 실행문이 없어 분리되지 않으므로 <*.gcsm> 인 경우도 추가한다.
           (_fileKind == d_Editor_FileKind_gcsm))) return(false);

  //}

  //[초기화]
  //{
      //[2012.06.09.토][추가!!!]
      infoCount = 0;

      line      = 0;

      changed   = false;

      //첫 항목은 항상 보관하고 시작.
      bfItem    = _cmtBlockInfo.items[0];

  //}

  //[부분 정보 수집]
  //{
      //[2012.06.12.화][추가!!!]{------------------------------------------------------
      //문서 처음부터 정보를 수집하지 않고 [편집기] 보이는 영역보다 하나 앞선 정보부터
      //시작하여 [보이는 영역] 바로 다음 정보까지 구한다.
      //이는 문서량이 많은 경우 처리 시간을 단축하기 위한것.
      //
      //처리할 모든 정보를 여기서 미리 계산.
      //
      //[2012.06.14.목][설명!!!]-------------------------------------------------------
      //모든 처리는 [보이는 영역(쪽)] 을 기준으로 처리되고 <_linetop_linenumber> 와
      //<_linetop_startindex> 정보가 [영역 시작] 정보가 된다.
      //
      //[구분!!!]----------------------------------------------------------------------
      //
      //<pPartInfo : true)  :
      //
      // - 보이는 영역 <_linetop_startindex> 의 바로 이전 [묶음주석] 정보에 따라 구분.
      //
      //   가) /* ... */ 사이에 <_linetop_startindex> 이 존재하는 경우
      //
      //   => <_linetop_startindex> 위치부터 검사 시작.
      //      즉, 현재 [항목] 의 "/*" 를 찾은 것으로 간주하고 "*/" 만 찾는다.
      //
      //      [중요!!!]{***************************************************************
      //      이는 문서 처음에 "/*" 이 있고 현재 <_linetop_startindex> 까지가 [수만줄]
      //      이라면 항상 [처음부터] 하는 것과 다를바 없기 때문에 이를 방지하고
      //      [문서량] 에 무관하게 항상 보이는 영역만 처리할수 있기 때문이다.
      //      //}**********************************************************************
      //
      //   나) /* ... */ 사이에 <_linetop_startindex> 이 존재하지 않는 경우.
      //
      //   => <_linetop_startindex> 부터 다시 "/*" 부터 찾는 일반 처리.
      //
      //<pPartInfo : false) :
      //
      // - 문서 처음부터 보이는 영역 끝까지.
      //   즉, [문서 처음부터] 정보를 수집하는지 아닌지의 차이가 있을뿐 끝은 같다.
      //}------------------------------------------------------------------------------

      if(pPartInfo == true)
      {
        //[초기화]
        //{
            //[중요!!!]{-----------------------------------------------------------
            //처음에는 반드시 <-1> 로 찾지 못한 것으로 정의해야 한다.
            //현재 <_linetop_startindex> 이전에 [묶음주석] 이 존재하지 않는 경우는
            //[묶음주석정보] 자체는 존재하더라도 찾는 것이 없기 때문에
            //<_linetop_startindex> 위치부터 검사해야 하기 때문이다.
            //
            //물론, 문서에서 [묶음주석] 이 하나도 없는 경우도 해당.
            //}--------------------------------------------------------------------

            cdItemIndex = -1;

        //}

        //[항목 찾기]
        //{
            //[!]{----------------------------------------------------------------
            //<_linetop_startindex> 이전 가장 가까운 마지막 [묶음주석] 항목 찾기.
            //}-------------------------------------------------------------------

            for(i = 0; i < _cmtBlockInfo.itemCount; i++)
            {
              //[!]{-------------------
              //"/*" 위치 정보만 대상.
              //}----------------------

              if(_cmtBlockInfo.items[i].startIndex <= _linetop_startindex)
              {
                //해당하는 것을 항상 기록해 놓으면 가장 마지막에 기록한 것이 찾는것에 해당.
                cdItemIndex = i;

              }
              else
              {
                break;

              }

            }

            //[!]{----------------------------------------
            //가장 마지막에 기록된 항목이 시작 항목 위치.
            //}-------------------------------------------

        //}

      }

      //[검사할 시작 행/위치 얻기]
      //{
          //[!]{----------------------------------------------------------------
          //[검사할 시작행] 은 [부분검사] 시에는 시작 항목의 [행 번호] 가 해당.
          //}-------------------------------------------------------------------

          if(pPartInfo == true)
          {
            //[!]{----------------------------------------
            //[부분검사] 인 경우.
            //
            //[주의!!!]-----------------------------------
            //[찾은것] 이 있는지 없는지에 따라 구분 처리.
            //}-------------------------------------------

            if(cdItemIndex >= 0)
            {
              //[!]{-----------------------------------------------------------------------
              //[묶음주석] 안에 <_linetop_startindex> 이 포함되는지 여부에 따라 구분 처리.
              //}--------------------------------------------------------------------------

              if((_cmtBlockInfo.items[cdItemIndex].startIndex <= _linetop_startindex) &&
                 (_linetop_startindex <= _cmtBlockInfo.items[cdItemIndex].endIndex))
              {
                //[!]{---------------------------------------------------------------
                //마지막 [묶음주석] 안에 <_linetop_startindex> 이 포함되는 경우는
                //"/*" 위치부터 다시 검사 시작.
                //
                //[2012.06.13.수][중요수정!!!]---------------------------------------
                //"/*" 와 <_linetop_startindex> 사이에 [수만줄] 이 있다면 검사시마다
                //[수만줄] 을 검사해야 하므로 [낭비] 가 된다.
                //이 경우는 이미 "/*" 정보는 알고 있으므로 이를 이용하여 "/*" 를
                //찾은 것으로 간주하고 "*/" 를 찾는 것만 처리한다.
                //단, <_linetop_startindex> 부터 찾으면 된다.
                //}------------------------------------------------------------------

                //이미 [묶음주석] 안이므로 [보이는 영역 처음] 부터 검사 시작.
                cdLineS   = _linetop_linenumber;
                index     = _linetop_startindex;

                //[주의!!!]{-----------------------------------------------------------------
                //찾은 [묶음주석] 의 "/*" 만 찾은 상태로 시작하므로 현재 [정보] 위치로 설정.
                infoCount = cdItemIndex;
                //}--------------------------------------------------------------------------

                //["/*" 를 찾은 상태로 만들기]
                //{
                    //[2012.06.13.수][추가!!!]{--------------------------------------------------
                    //이미 확정된 정보이므로 다른 것은 그대로 두고 [상태] 만 조성.
                    //
                    //[2012.06.19.화][수정!!!]---------------------------------------------------
                    //"/*" 시작위치와 <_linetop_startindex> 가 같은 위치인 경우는
                    //반드시 "/*" 위치부터 다시 검사한다.
                    //설정시에는 문제가 없는데 [해제] 시에는 실제 "/*" 는 해제 상태
                    //인데 "*/" 위치만 찾기 때문에 [해제 가 반영이 안된다.
                    //"/*" 부터 다시 검사하는 경우는 "/*" 이 해제된 것으로 보기 때문에
                    //이 부분의 [묶음주석] 정보는 자동으로 [삭제] 된다.
                    //금일 이 부분 발견하고 수정한다.
                    //
                    //문서 처음 [0] 위치에 "/*" 를 입력시에는 [묶음주석] 이 잘 동작했는데
                    //"*" 를 삭제했음에도  [묶음주석] 이 해제되지 않았다.
                    //원인은 "/*" 한개로 문서끝까지 [묶음주석] 이 한개 정보로 정리된것인데
                    //삭제된 "/*" 부분을 건너 뛰고 "*/" 만 찾으려니 존재하지 않고 결국
                    //다시 [문서끝] 까지를 [묶음주석] 으로 보게 되어 정보가 수정이 안된것이었다.
                    //
                    //"/*" 부터 다시 검사하면 간단하게 해결된다.
                    //}--------------------------------------------------------------------------

                    if(_cmtBlockInfo.items[cdItemIndex].startIndex < _linetop_startindex)
                    {
                      //[2012.06.19.화][수정!!!]{-----------------------------------
                      //"/*" 시작 위치와 <_linetop_startindex> 위치가 같은 경우라면
                      //항상 "/*" 부터 다시 처리해야 한다.
                      //}-----------------------------------------------------------

                      //[이전 항목 보관]
                      //{
                          //[!]{--------------------------------------------
                          //같은 항목이나 "/*" 는 그대로지만 "*/" 은 위치가
                          //수정될수 있으므로 이 정보는 유효한 것.
                          //}-----------------------------------------------

                          bfItem = _cmtBlockInfo.items[infoCount];

                      //}

                      //[시작 상태 만들기]
                      //{
                          //[/* ... */] 주석문이 시작된 것으로 본다.
                          whatIn = 'r';

                      //}

                    }

                //}

              }
              else
              {
                //[!]{------------------------------------------------------------
                //찾은 [묶음주석] 안에 <_linetop_startindex> 이 포함되지 않는다면
                //<_linetop_startindex> 위치부터 새로 검사 시작.
                //즉, "/*" 부터 찾는다.
                //}---------------------------------------------------------------

                cdLineS   = _linetop_linenumber;
                index     = _linetop_startindex;

                //[주의!!!]{-----------------
                //찾은 위치 다음부터 추가.
                infoCount = cdItemIndex + 1;
                //}--------------------------

              }

            }
            else
            {
              //[주의!!!]{---------------------------------------------------------------
              //현재 <_linetop_startindex> 위치 이전에는 [묶음주석] 이 존재하지 않는 것.
              //이 경우는 <_linetop_startindex> 위치부터 검사.
              //즉, 현재 보이는 영역이전까지 [묶음주석] 이 하나도 없는 경우.
              //}------------------------------------------------------------------------

              cdLineS   = _linetop_linenumber;
              index     = _linetop_startindex;
              infoCount = 0;

            }

          }
          else
          {
            //[!]{-------------------------------------
            //[전체검사] 인 경우는 항상 첫행부터 검사.
            //}----------------------------------------
            
            cdLineS   = 0;
            index     = 0;
            infoCount = 0;

          }

      //}

      //[검사할 마지막 행 얻기]
      //{
          //[!]{-------------------------------------------------------
          //[마지막행] 은 [전체/부분:검사] 모두 [보이는 영역 끝] 까지.
          //}----------------------------------------------------------
          
          //넉넉하게 3줄 정도 여유를 준다.
          cdLineE = _linetop_linenumber + (this->Height/_line_height) + 3;

          //[주의!!!]{------------------------
          //검사를 처음 시작하는 행번호 기록.
          line = cdLineS;
          //}---------------------------------

      //}

  //}

  START:

  //[문서 끝인지 검사]
  //{
      //[!]{-------------------------------------------------------------------------------------
      //문자를 추출하기 전에 먼저 [문서:끝] 인지 검사.
      //소스의 끝이 단어로 유용하지 않은 문자가 온 경우(CRLF 등)는 [문서] 끝을 넘는 경우가 발생.
      //이는 <Parser()> 자체 안에서는 막을수 없으므로 아예 이 함수안에서 검사.
      //}----------------------------------------------------------------------------------------

      if((index >= _filesize) ||
         //[2012.06.12.화][추가!!!]
         //[지정행] 까지만 처리.
         (line > cdLineE))
      {
        //문서 끝에 도달한 경우.

        //[2009.06.04.목][수정!!!]{-------------------------------------
        //한줄 주석으로 끝나는 경우는 제외한다.
        //그렇지 않은 경우는 문서 전체가 [묶음주석] 인 것으로 간주된다.
        //이 함수는 오직 [묶음주석] 정보만 처리되어야 하므로...
        //}-------------------------------------------------------------

        if(whatIn == 'r')// ||(whatIn == 'h'))
        {
          //[!]{----------------------------------------
          //[주석문] 안인 상태로 문서가 종료되는 경우.
          //현재 정보를 마무리 한다.
          //[묶음주석 이 "*/" 로 마무리 된 것으로 처리.
          //}-------------------------------------------
          
          _cmtBlockInfo.items[infoCount].endIndex = index;
          _cmtBlockInfo.items[infoCount].endLine  = line;
          infoCount++;

          //[행 변화 판별]
          //{
              //[2012.06.11.월][추가!!!]
              if(bfItem.endLine != line) { changed = true; }

          //}

        }

        //문서 끝이므로 더이상 처리하지 않는다.
        goto lbEnd;

      }

  //}

  //[문자 추출]{-----------
  chr = _editbuf[index++];
  //}----------------------

  //[공백/탭 거르기]{------------------------------------
  //[공백/탭] 문자 무시.
  if     ((chr == ' ') || (chr == '\t')) { goto START; }
  //[2012.06.09.토][추가!!!]-----------------------------
  //[행] 관리.
  //CR 만 검사하고 <CRLF> 로 한개 행으로 간주.
  else if(chr == '\r')                   { line++;     }
  //}----------------------------------------------------

  //[!]{--------------------------------------------
  //여기까지 온것은 공백이 아니므로 해당 처리 수행.
  //}-----------------------------------------------

  if(chr == '*')
  {
    //[문자 추출]{-----------
    chr = _editbuf[index++];
    //}----------------------

    if(chr == '/')
    {
      if(whatIn ==  'r')
      {
        //[주석문 해제]
        //{
            //[묶음주석 끝]
            //{
                //한개의 [묶음주석] 이 끝났다.
                _cmtBlockInfo.items[infoCount].endIndex = index - 1;
                _cmtBlockInfo.items[infoCount].endLine  = line;
                infoCount++;

                //[행 변화 판별]
                //{
                    //[2012.06.11.월][추가!!!]
                    if(bfItem.endLine != line) { changed = true; }

                //}

            //}

            //이제까지 /* ... */ 주석문 안이었으므로 주석문 해제.
            whatIn = 0;

            goto START;

        //}

      }

      //계속 검사한다.
      goto START;

    }
    else
    {
      //[!]{------------------------------
      //이 경우는 '*' 단독으로 사용된 것.
      //}---------------------------------

      //이미 증가한 index 값은 다시 이전 문자 위치로 돌려 놓아야 한다.
      index--;

      //계속 검사한다.
      goto START;

    }

  }

  if(chr == '/')
  {
    //[문자 추출]{-----------
    chr = _editbuf[index++];
    //}----------------------

    if(chr == '*')
    {
      if(whatIn == 0)
      {
        //[주석문 시작]
        //{
            //[이전 항목 보관]
            //{
                //[2012.06.11.월][추가!!!]
                bfItem = _cmtBlockInfo.items[infoCount];

            //}

            //[주석문 묶음 시작]
            //{
                //한개의 [주석묶음] 이 시작된다.
                _cmtBlockInfo.items[infoCount].startIndex = index - 2;
                _cmtBlockInfo.items[infoCount].startLine  = line;

            //}

            //[행 변화 판별]
            //{
                //[2012.06.11.월][추가!!!]
                if(bfItem.startLine != line) { changed = true; }

            //}

            // /* ... */ 주석문이 시작된 것으로 본다.
            whatIn = 'r';

            //주석문의 경우는 단어로 반환할 필요가 없으므로 다음 단어 검사로 넘어간다.
           goto START;

        //}

      }

      //계속 검사한다.
      goto START;

    }
    else if(chr == '/')
    {
      if(whatIn == 0)
      {
        //[주석문 시작]{-----------------------------------------------------------
        // // ... 주석문이 시작된 것으로 본다.
        whatIn = 'h';
        //주석문의 경우는 단어로 반환할 필요가 없으므로 다음 단어 검사로 넘어간다.
        goto START;
        //}------------------------------------------------------------------------

      }

      //계속 검사한다.
      goto START;

    }
    else
    {
      //[!]{------------------------------
      //이 경우는 '/' 단독으로 사용된 것.
      //}---------------------------------

      //이미 증가한 index 값은 다시 이전 문자 위치로 돌려 놓아야 한다.
      index--;

      //계속 검사한다.
      goto START;

    }

  }

  //[!]{------------------------------------
  //문자 한개만으로 이루어진 [연산자] 검사.
  //}---------------------------------------

  if(chr == '\r') //CR
  {
    if(_editbuf[index] == '\n')
    {
      //[index 증가]
      //{
          //[!]{-------------------------------------------------------------------------
          //이 경우는 [CRLF] 가 된것으로 행정보만 수정하고 단어로 반환하지는 않아야한다.
          //이미 LF 문자인지는 알고 있고, 단어로 반환하지는 않으므로 그냥 문자 위치만
          //증가시켜주기만 하면 된다.
          //}----------------------------------------------------------------------------

          index++;

      //}

      //[주석문 해제]
      //{
          //[!]{----------------------------------------------------------
          //만일 현재 [// ...] 주석문 안이라면 행이 바뀌었으므로 주석문을
          //해제해 주어야 한다.
          //}-------------------------------------------------------------

          if     (whatIn == 'h') { whatIn = 0; }
          //[2012.05.09.수][추가!!!]{----------------------------------------
          //[문자상수], [문자열] 역시 행이 바뀌는 경우 해당 영역이 종료된다.
          else if(whatIn == 'c') { whatIn = 0; }
          else if(whatIn == 's') { whatIn = 0; }
          //}----------------------------------------------------------------

      //}

      goto START;


    }

    //[!]{-------------------------------------------------------------------------------
    //여기까지 온것은 CRLF 로 사용된 것이 아니므로 '\r' 을 하나의 문자로 보고 계속 처리.
    //}----------------------------------------------------------------------------------

    //계속 검사한다.
    goto START;

  }

  //[주의!!!]{---------------------------------------------------------------
  //[CRLF(\r\n) 으로 사용된 것이라면 위의 '\r' 처리 부에서 '\n' 도 같이 처리
  //되어 이곳까지 올수 없다. 그러므로, 이 경우는 '\r' 없이 '\n' 만 온것으로
  //한개의 문자로 본다.
  //}------------------------------------------------------------------------

  if(chr == '\'')
  {
    //[!]{-------------
    //[문자상수] 부분.
    //}----------------

    //[2005.09.23.금][추가!!!]
    switch(whatIn)
    {
      case 0 :
      {
        //' ... ' 문자 상수가 시작된 것으로 본다.
        whatIn = 'c';

      } break;

      case 'c' :
      {
        //이제까지 문자상수 안이었으므로 영역을 끝낸다.
        whatIn = 0;

      } break;

    }

    //계속 검사한다.
    goto START;

  }

  if(chr == '\"')
  {
    //[!]{-----------
    //[문자열] 부분.
    //}--------------

    switch(whatIn)
    {
      case 0 :
      {
        //" ... " 문자열의 시작으로 본다.
        whatIn = 's';

      } break;

      case 's' :
      {
        //이제까지 문자열 안이었으므로 문자열을 끝낸다.
        whatIn = 0;

      } break;

    }

    //계속 검사한다.
    goto START;

  }

  //문서 끝까지 계속 검사한다.
  goto START;


  lbEnd:

  //[개수 기록]
  //{
      //[2012.06.09.토][추가!!!]{---
      //수집된 정보 개수 기록.
      //}---------------------------

      //[항목수 변경 검사]
      //{
          //[2012.06.11.월][추가!!!]{-----------------------------------------------
          //[묶음주석] 이 [추가/삭제] 된 경우이므로 [수정] 으로 전체 그리기로 판별.
          //}-----------------------------------------------------------------------

          if(_cmtBlockInfo.itemCount != infoCount) { changed = true; }

      //}

      //현재 처리된 항목수 설정.
      _cmtBlockInfo.itemCount = infoCount;

  //}

//[2012.06.13.수][추가!!!]{---------------------------
//실시간으로 [묶음주석] 정보 개수를 보고자 할때 사용.
//Ide_Test(_cmtBlockInfo.itemCount);
//}---------------------------------------------------

  //[상태 반환]
  //{
      //[2012.06.11.월][추가!!!]
      return(changed);

  //}

}

bool __fastcall Teditor_edit_Form::_CommentBlock_Check_Word(int  pWordIndex)
{
  //[2009.06.02.화][생성!!!]{---------------------------------------------
  //이 위치의 단어가 [묶음주석] 범위에 있는지 확인하고 안에 있는 경우라면
  //<true> 를 반환한다.
  //}---------------------------------------------------------------------

  //[VAR]
  //{
      int i;

  //}
  
  for(i = 0; i < _cmtBlockInfo.itemCount; i++)
  {
    if((_cmtBlockInfo.items[i].startIndex <= pWordIndex) &&
       (pWordIndex <= _cmtBlockInfo.items[i].endIndex))
    {
      //현재 [묶음주석] 안이다.
      return(true);

    }

  }

  //현재 [묶음주석] 밖에 있는 것이다.
  return(false);

}

/*
//[2009.06.03.수][폐기!!!]{------------------------------------------------------------------------
//이 함수는 필요가 없다.
//의도는 좋았으나 어던 것이든 추가하거나 삭제하여 문서가 변경되면 이전의 [묶음주석] 의 위치도 전부
//변경되므로 결국 이전에 정리해 놓은 것은 아무 의미가 없어진다.
//따라서, 문서가 변경되어 한개의 문자라도 추가/삭제된 경우는 무조건 다시 구해 주어야 한다.
//이 함수는 의미가 없으므로 금일 폐기한다.
//}------------------------------------------------------------------------------------------------

bool __fastcall Teditor_edit_Form::_CommentBlock_SymbolCheck(char  *pStr,
                                                             //<pStr: NULL> 인 경우만 유효하다.
                                                             //문자열을 사용하는 경우는 그냥 0 을 준다(아무것이나 무관하다).
                                                             int    pStartIndex,
                                                             int    pEndIndex)
{
  //[2009.06.02.화][생성!!!]{---------------------------------------------------
  //전달 받은 문자열 안에 [묶음주석] 을 구성하는 "/ *" 나 "* /" 이 있는지
  //확인하고 있다면 <true> 를 반환한다.
  //이는 [붙이기/되돌리기/되살리] 에서 계속 [묶음주석] 의 정보를 수집하는데
  //많은 시간을 끌지 않고 고속으로 처리하도록 하기 위한 것으로 꼭 필요한
  //경우만 처리하기 위한 것이다.
  //이 두개 구성 문자가 있는 경우는 위의 3경우 다시 [묶음주석] 을 구성할
  //가능성이 있으므로 이를 위한 것이다.
  //
  //경우에 따라 [선택영역] 안의 문자열을 처리 할 경우도 있으므로 이 경우는
  //<pStr : NULL> 인 경우로 전달받은 문자열의 시작과 끝 위치를 가지고 처리한다.
  //}---------------------------------------------------------------------------

  //[VAR]
  //{
      int i;

  //}

  if(pStr != NULL)
  {
    for(i = 0; pStr[i] != '\0'; i++)
    {
      if(((pStr[i] == '/') && (pStr[i + 1] == '*')) ||
         ((pStr[i] == '*') && (pStr[i + 1] == '/')))
      {
        //구성문자중 한개는 존재한다.
        return(true);

      }

    }

  }
  else
  {
    for(i = pStartIndex; i < pEndIndex; i++)
    {
      if(((pStr[i] == '/') && (pStr[i + 1] == '*')) ||
         ((pStr[i] == '*') && (pStr[i + 1] == '/')))
      {
        //구성문자중 한개는 존재한다.
        return(true);

      }

    }

  }

  //문자열 안에 [묶음주석] 구성 문자가 존재하지 않는다.
  return(false);

}
*/

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

bool __fastcall Teditor_edit_Form::_EDITBUF_LINE_Out(int   pX,
                                                     int   pY,
                                                     int   pLINEstartindex,
                                                     int  *rLINEendindex)
{
  //[2007.01.22.월][생성!!!]{-----------------------------------------------------------------------------------------
  //FONT_Out_LineStr_withSTARTENDindex() 함수를 대체한다.
  //한행에서만 유효하고 _editbuf[] 에서 지정된 행의 시작 위치부터 이 행의 끝까지(CRLF 또는 '\0' 까지)
  //문자열을 여러 설정을 적용하여 출력한다.(선택, 문법강조 등)
  //한 행만을 대상으로 하므로 CRLF 는 처리하지 않고 단지 '\t' 만 구분하여 처리한다.
  //이 함수는 한개의 행을 출력하는 기본함수이고 반드시 행을 출력하는 경우는 이 함수를 사용해야 한다.
  //
  //_block_startindex, _block_endindex 사이에 처리 문자가 위치한 경우는 [반전출력 영역] 에 있는 것이므로
  //지정 색을 반전 시켜준다.
  //
  //[2007.02.01.목][수정!!!]------------------------------------------------------------------------------------------
  //_EDITBUF_STRING_Out() 함수에서 이 함수를 연속으로 사용하여 여러줄을 출력할때 다음행의 시작위치를
  //다시 구하지 않고 바로 알수 있도록, 이 함수가 처리한 행의 끝 위치를 반환한다.
  //이는 일반적으로 _lineednindex 와 같은 의미이다. 즉, 마지막 문자 + 1 의 위치가 된다.
  //
  //[2007.02.05.월][수정!!!]------------------------------------------------------------------------------------------
  //[굵은글꼴] 을 사용할수 있게 수정되었다.
  //이에 따라 FONT_Out_Moonja2() => FONT_Out_StyleMoonja() 함수로 교체 되었다.
  //
  //[2007.02.06.화][수정!!!]------------------------------------------------------------------------------------------
  //(_select_start.caret_index < _select_end.caret_index) 의 관계가 꼭 성립되는 것은 아니므로 서로의 크기를 비교하여
  //처리하는 것으로 다시 수정한다.
  //이는 단지 시작과 끝의 위치를 가지고 있는 것일 뿐이며, [선택영역] 은 아래에서 위로 형성되 갈수 있기
  //때문이다.
  //
  //[2007.02.06.화][수정!!!]------------------------------------------------------------------------------------------
  //_select_start.caret_index, _select_end.caret_index 둘 중 하나라도 -1 인 경우는 [선택영역] 이 없는 것이므로
  //아예 따질 필요는 없다.
  //
  //[2007.02.08.목][수정!!!]------------------------------------------------------------------------------------------
  //j  를 직접 증가 하는 경우 [선택영역처리] 부분에서 이미 증가되어 변경된 j 값을 사용하게 되므로
  //정확한 단어의 위치를 알수 없게 된다. 따라서, j 는 j_add 에 증가할 값을 기록해 놓은 다음에
  //이 값으로 [선택영역처리] 후에 증가시킨다.
  //
  //[2007.04.15.일][추가!!!]------------------------------------------------------------------------------------------
  //현재 출력 행이 [정지점] 이 지정된 행이라면 출력 문자열 속정이 전부 적용된 상태에서
  //다시 [정지점] 지정색 을 사용하여 처리해야 한다.
  //C++Builder 와 비슷한 모양으로 처리한다.
  //
  //[2009.05.09.토][기능추가!!!]--------------------------------------------------------------------------------------
  //[전체찾기] 기능의 경우 전용 공간에 [찾을문자열] 을 등록하면 자동으로 행마다 이 문자열을 찾아서 지정된 전용
  //색으로 다시 입혀준다.
  //이는 다른 [색동문자] 기능이 다 처리된후 [선택영역] 지정 전에 처리되어야 한다.
  //따라서, 찾고하 하는 문자열 [편집기] 상에 전부 동시에 표시 되므로 시인성을 높일수 있다.
  //일단 [찾기대화상자] 의 [찾을문자열] 이 있는 경우는 자동으로 무조건 칠해주는 것으로 처리한다.
  //
  //[2012.05.24.목][수정!!!]------------------------------------------------------------------------------------------
  //[실시간 선언 정보판] 의 [대상 단어] 를 [밝은 은색] 으로 지정.
  //단, [실시간 선언 정보판] 이 보이고 있는 경우만 처리.
  //
  //[2012.06.08.금][추가!!!]------------------------------------------------------------------------------------------
  //[세로줄] 그리기 추가.
  //
  //[2019.01.08.화][수정!!!]------------------------------------------------------------------------------------------
  //[찾을 문자열] 이외에 [교환 문자열] 도 [형광문자] 를 지원하도록 수정.
  //}-----------------------------------------------------------------------------------------------------------------

  //[VAR]
  //{
      //출력한 [문자] 의 영역 크기.
      int               moonja_width;
      int               moonja_height;

      //2byte-code 문자의 code.
      unsigned short    code;

      bool              select_enable = false;
      struct CARETINFO  select_start,
                        select_end;
      int               i, j, j_add;

      int               front_color;
      int               back_color;
      bool              transparent;
      int               style = d_FONTSTYLE_default;

      //[2007.04.15.일][추가!!!]
      bool              breakpoint_line = false;

      //[찾을 문자열]
      //{
          //[2009.05.09.토][추가!!!]{--------------------------------
          //[찾기 대화상자:찾을 문자열] 의 [형광문자] 지원을 위한것.
          //}--------------------------------------------------------
          
          //찾고자 하는 문자열의 [시작/끝 위치] 를 관리한다.
          int   findWordStartIndex = pLINEstartindex; //단어의 시작위치.
          int   findWordEndIndex   = pLINEstartindex; //단어의 끝위치는 다음 문자위치.

          //찾은 경우는 true.
          bool  findWord = true; //처음 한번은 찾아야 한다.

      //}

      //[교환 문자열]
      //{
          //[2019.01.08.화][추가!!!]{--------------------------------
          //[찾기 대화상자:교환 문자열] 의 [형광문자] 지원을 위한것.
          //}--------------------------------------------------------

          //찾고자 하는 문자열의 [시작/끝 위치] 를 관리한다.
          int   replaceWordStartIndex = pLINEstartindex; //단어의 시작위치.
          int   replaceWordEndIndex   = pLINEstartindex; //단어의 끝위치는 다음 문자위치.

          //찾은 경우는 true.
          bool  replaceWord = true; //처음 한번은 찾아야 한다.

      //}

      //이 행의 끝위치(검사 범위를 이 행으로 한정하기 위한 것).
      int   lineEndIndex;

      //[2010.02.16.화][추가!!!]
      //현재 행번호를 가진다.
      int   thisLineNum;

  //}

  //[초기화]
  //{
      //일단 시작 위치값으로 초기화 한다.
      (*rLINEendindex) = pLINEstartindex;

  //}

  //[선택영역 정보 정리][2007.02.06.화][추가!!!]
  //{
      //전용 함수로 크기순으로 정리된 <start/end index> 값을 얻는다.
      select_enable = _SELECT_Get_StartEndIndex(&select_start, &select_end);

  //}

  //[현재행 구하기]
  //{
      //[2010.02.14.일][추가!!!]
      thisLineNum = (pY - _text_org_y) / _line_height;

  //}

  //[정지점 확인]
  //{
      //[2007.04.15.일][추가!!!]{-----------------------------------------
      //현재 출력하는 행이 [정지점] 이 있는 행인 경우 이를 기록한다.
      //[정지줄] 의 색처리를 출력 문자열에 적용하기 위한 것이다.
      //
      //[2010.02.16.화][수정!!!]------------------------------------------
      //<thisLineNum> 로 처리하는 것으로 수정.
      //<thisLineNum> 이 정보는 아래의 [지정행] 을 처리하는데도 사용된다.
      //}-----------------------------------------------------------------

      if(_BREAKPOINT_Search(thisLineNum) >= 0) breakpoint_line = true;

  //}

  //[현재행 문자열 정보얻기]
  //{
      //행 문자열의 문법 강조등의 정보를 얻는다. 결과는 해당 전역변수에 저장된다.
      _MOONJACONFIG_LineGet(pLINEstartindex, &lineEndIndex);

  //}

  //[문자열 출력]
  //{
      //[설명]{-----------------------------------------------------------------------
      //[반전출력 영역] 인지 구분하고, 그외 [문법강조] 등의 처리도 이곳에서 처리한다.
      //이미 문자 정보가 정리된 상태이므로 이 정보를 사용한다.
      //
      //CRLF : 발견 즉시 종료한다.(이 함수는 한개의 행만 처리하므로...)
      //       또는 '\0' 즉, 문서의 끝에 도달한 경우도 종료해야 한다.
      //'\t' : [공백] 으로 변환 처리한다.
      //}-----------------------------------------------------------------------------

      //_wordconfig[] 를 하나씩 읽어서 처리한다.
      for(i = 0, j = pLINEstartindex; i < _wordconfig_count; i++)
      {
        //해당 단어의 문자를 하나씩 읽어서 처리한다.
        for(j = _wordconfig[i].index; j < (_wordconfig[i].index + _wordconfig[i].length) ; j += j_add)
        {
          //[찾을 단어 찾기]
          //{
              //[찾을 문자열] 이 있는 경우만 처리한다.
              if(find_DialogBox_Form->_find_Edit->_editbuf[0] != '\0')
              {
                //[새로 찾아야 하나?]
                //{
                    //처음이거나 [단어범위] 를 넘은 경우는 다시 [찾을 문자열] 을 찾는다.
                    if(//이 행에서 찾지 못한 경우는 더이상 처리하지 않는다.
                       (findWord == true) &&
                       //이전에 찾은 단어 끝 위치를 벗어난 경우는 새로 찾는다.
                       (findWordEndIndex <= j))
                    {
                      //[찾을 문자열] 을 다시 찾는다.
                      STR_Find(_editbuf,
                               //[중요!!!]{----------------------------------------------------------------
                               //한개의 행만 검사대상으로 해야 하므로 이행의 끝위치를 크기로 입력해야한다.
                               //문서크기 전체를 입력하면 매번 끝까지 검사하므로 엄청난 시간 낭비가 된다.
                               lineEndIndex,
                               //}-------------------------------------------------------------------------
                               //이전 단어의 끝위치 부터 다시 찾는다.
                               findWordEndIndex,
                               //찾을조건.
                               find_DialogBox_Form->_word_CheckBtn->_checked,
                               find_DialogBox_Form->_case_CheckBtn->_checked,
                               //찾을 문자열.
                               find_DialogBox_Form->_find_Edit->_editbuf,
                               //찾은 단어 시작 위치.
                               &findWordStartIndex);

                      //단어 끝위치 구하기(다음 문자의 시작위치로 정의한다).
                      findWordEndIndex = findWordStartIndex + STR_Length(find_DialogBox_Form->_find_Edit->_editbuf);

                      //단어를 찾았다는 것을 알려준다.
                      //이는 더이상 이 행에 찾을 단어가 없는 경우는 더이상 찾지 않게 위한 것이다.
                      if(findWordStartIndex != -1) { findWord = true;  }
                      else                         { findWord = false; }

                    }

                //}

              }

          //}

          //[교환 단어 찾기]
          //{
              //[2019.01.08.화][추가!!!]

              //[교환 문자열] 이 있는 경우만 처리한다.
              if(find_DialogBox_Form->_replace_Edit->_editbuf[0] != '\0')
              {
                //[새로 찾아야 하나?]
                //{
                    //처음이거나 [단어범위] 를 넘은 경우는 다시 [교환 문자열] 을 찾는다.
                    if(//이 행에서 찾지 못한 경우는 더이상 처리하지 않는다.
                       (replaceWord == true) &&
                       //이전에 찾은 단어 끝 위치를 벗어난 경우는 새로 찾는다.
                       (replaceWordEndIndex <= j))
                    {
                      //[찾을 문자열] 을 다시 찾는다.
                      STR_Find(_editbuf,
                               //[중요!!!]{----------------------------------------------------------------
                               //한개의 행만 검사대상으로 해야 하므로 이행의 끝위치를 크기로 입력해야한다.
                               //문서크기 전체를 입력하면 매번 끝까지 검사하므로 엄청난 시간 낭비가 된다.
                               lineEndIndex,
                               //}-------------------------------------------------------------------------
                               //이전 단어의 끝위치 부터 다시 찾는다.
                               replaceWordEndIndex,
                               //찾을조건.
                               find_DialogBox_Form->_word_CheckBtn->_checked,
                               find_DialogBox_Form->_case_CheckBtn->_checked,
                               //찾을 문자열.
                               find_DialogBox_Form->_replace_Edit->_editbuf,
                               //찾은 단어 시작 위치.
                               &replaceWordStartIndex);

                      //단어 끝위치 구하기(다음 문자의 시작위치로 정의한다).
                      replaceWordEndIndex = replaceWordStartIndex + STR_Length(find_DialogBox_Form->_replace_Edit->_editbuf);

                      //단어를 찾았다는 것을 알려준다.
                      //이는 더이상 이 행에 찾을 단어가 없는 경우는 더이상 찾지 않게 위한 것이다.
                      if(replaceWordStartIndex != -1) { replaceWord = true;  }
                      else                            { replaceWord = false; }

                    }

                //}

              }

          //}  

          if     (_editbuf[j] == '\0')
          {
            //[문서끝] 이라면 더이상 처리하지 않는다.
            goto END;

          }
          else if((_editbuf[j    ] == 0x0d) &&
                  (_editbuf[j + 1] == 0x0a))
          {
            //CRLF 인 경우는 행 끝이므로 더이상 처리하지 않는다.
            goto END;

          }
          else if(_editbuf[j] < 0)
          {
            //첫 byte 가 [음수] 라면 [한글/기호/한자] 이다.

            //2byte-code 합성.
            code = ((((unsigned short)_editbuf[j    ]) << 8) & 0xff00) |
                   ((((unsigned short)_editbuf[j + 1]) << 0) & 0x00ff);

            j_add = 2;

          }
          else if(_editbuf[j] == '\t')
          {
            //<tab> 의 경우는 [공백] 으로 대체한다.
            code = ' ';

            j_add = 1;

          }
          else
          {
            //[영문] 이 해당한다.
            code = _editbuf[j];

            j_add = 1;

          }

          //[설정적용]
          //{
              front_color = _wordconfig[i].front_color;
              back_color  = _wordconfig[i].back_color;
              transparent = _wordconfig[i].transparent;
              style       = _wordconfig[i].style;

          //}

          //[정지점 적용]
          //{
              //[2007.04.15.일][추가!!!]{---------------------------------------------
              //현재 행이 [정지점] 이 있는 행인 경우는 [정지점] 색과 합성처리를 한다.
              //C++Builder 처럼 문자색은 [흰색], 바탕은 [정지점색] 으로 처리한다.
              //[선택적용] 보다 먼저 처리하는 것이 더 자연스럽다.
              //}---------------------------------------------------------------------

              if(breakpoint_line == true)
              {
                //24bit 색을 사용하므로 하위3 byte 만 반전시켜야 한다.(결과는 0x00xxxxxx 이 되야 한다.)
                front_color = clWhite          & 0x00ffffff;
                back_color  = _breakline_color & 0x00ffffff;
                transparent = false;

              }

          //}

          //[지정행 적용]
          //{
              //[2007.04.15.일][추가!!!]{--------------
              //[지정행] 을 해당 설정으로 색을 입힌다.
              //}--------------------------------------

              //현재 행이 [지정행] 인 경우만 처리한다.
              if(_focusLineNum == thisLineNum)
              {
                //24bit 색을 사용하므로 하위3 byte 만 반전시켜야 한다.(결과는 0x00xxxxxx 이 되야 한다.)
                front_color = _focusLineFontColor & 0x00ffffff;
                back_color  = _focusLineBackColor & 0x00ffffff;
                transparent = false;

              }

          //}

          //[찾은 문자열 표시]
          //{
              //[2009.05.09.토][추가!!!]{-----------------------------------------------
              //[찾은 문자열] 은 전용 색상과 설정을 준다.
              //위에서 [정지점행] 으로 바탕이 지워지는것을 막기 위하여 여기서 처리한다.
              //}-----------------------------------------------------------------------

              if((findWord == true) && (findWordStartIndex <= j) && (j < findWordEndIndex))
              {
                front_color = _wordconfig[i].front_color;
                back_color  = clLime; //형광펜같은 밝은 연두색으로 바탕을 칠한다.
                transparent = false;  //배경색을 칠하기 위한 것이다.

              }

          //}

          //[교환 문자열 표시]
          //{
              //[2019.01.08.화][추가!!!]{-----------------------------------------------
              //[교환 문자열] 은 전용 색상과 설정을 준다.
              //위에서 [정지점행] 으로 바탕이 지워지는것을 막기 위하여 여기서 처리한다.
              //}-----------------------------------------------------------------------

              if((replaceWord == true) && (replaceWordStartIndex <= j) && (j < replaceWordEndIndex))
              {
                front_color = _wordconfig[i].front_color;

                //back_color  = 0x00ff80ff;//0x00c080ff; //0x008080ff
                BMP_Get_Bright_Color(clRed, 165, &back_color);

                transparent = false;  //배경색을 칠하기 위한 것이다.

              }

          //} 

          //[선택영역적용]
          //{
              //[선택영역] 이 유효한 경우만 처리한다.
              if(select_enable == true)
              {
                if((select_start.caret_index <= j) && (j < select_end.caret_index))
                {
                  //[!]{----------------------------------------------------------------------------------
                  //현재 문자가 [선택영역] 에 있으므로 현재 이 문자의 속성에 지정된 모든 색을 반전시키고,
                  //[배경투명속성] 을 해제한다.
                  //}-------------------------------------------------------------------------------------

                  //24bit 색을 사용하므로 하위3 byte 만 반전시켜야 한다.(결과는 0x00xxxxxx 이 되야 한다.)
                  front_color = (~front_color) & 0x00ffffff;
                  back_color  = (~back_color)  & 0x00ffffff;
                  transparent = false;

                }

              }

          //}

          //[실시간 선언 정보판:대상단어]
          //{
              //[2012.05.24.목][추가!!!]{-------------------------------------------------------------
              //[실시간 선언 정보판] 의 대상이 되는 [단어] 를 [색동문자] 로 지정.
              //이는 [정보판] 이 원래는 [단어] 시작 아래에 위치하게 되는데 [화면영역] 을
              //벗어나는 경우 자동으로 위치가 이동하게 되는 경우, [단어] 시작 아래에
              //반드시 위치한다는 보장이 없으므로 어떤 [단어] 를 대상으로 한 정보인지
              //구분할수 없게 된다.
              //이를 방지하기 위하여 [대상 단어] 를 별도 [형광문자] 로 지정한다.
              //
              //[참고!!!]-----------------------------------------------------------------------------
              //[문자] 단위로 모두 개별적 처리가 가능하지만 일단 [단어] 단위로만 처리한다.
              //
              //[2012.05.25.금][수정!!!]
              //[단어색/배경색] 으로 지정하는 것은 [단어] 아래에 나오는 [실시간 선언 정보판] 과
              //어울리지 않고 보기 좋지 않다.
              //가장 보기 좋은 것이 [단어] 에 [밑줄] 을 긋는 경우이다.
              //따라서, 여기서는 처리하지 않고 다음 [문자출력] 부분에서 [밑줄] 을 긋는 것만 처리한다.
              //}-------------------------------------------------------------------------------------

              /*
              if(info_tree_Form != NULL)
              {
                if(info_tree_Form->Visible == true)
                {
                  if((_wordStartIndex <= j) && (j < _wordEndIndex))
                  {
                    front_color = _wordconfig[i].front_color;//_ide_option->color_0;// _wordconfig[i].front_color;
                    //[은색] 보다 밝은 색으로 [암시] 를 주는 정도로 설정.
                    back_color  = info_tree_Form->_backColor; //0xe0e0e0;
                    transparent = true;//false;
                    //style       = d_FONTSTYLE_bold;

                  }

                }

              }
              */

          //}

          //[문자출력]
          //{
              //[2012.05.25.금][추가!!!]{--------------------------------------------------
              //[실시간 선언 정보판] 이 보이는 경우는 [대상 단어] 아래에 [형광색] 으로
              //밑줄을 그어 [지정] 해 준다.
              //이는 [화면영역] 에 항상 [실시간 선언 정보판] 이 보이도록 자동 이동하는경우
              //어떤 단어를 대상으로 하는지 알수 없기 때문에 필요하다.
              //즉, 어떤 경우라도 현재 [대상 단어] 를 확실하게 인식시키기 위한것.
              //}--------------------------------------------------------------------------

              if((info_tree_Form != NULL) && (info_tree_Form->Visible == true) &&
                 ((_wordStartIndex <= j) && (j < _wordEndIndex)))
              {
                //[!]{-----------------------------------
                //[실시간 선언 정보판] 지정 단어인 경우.
                //}--------------------------------------

                if(FONT_Out_StyleMoonja(_bmp_, &_font, pX, pY, front_color, back_color, transparent, style, code,
                                        //[형광색] 으로 밑줄을 긋는다.
                                        d_FONT_underline_line, false, 0, clLime,
                                        &moonja_width, &moonja_height) != true)
                {
                  return(false);

                }

              }
              else
              {
                //[!]{--------------
                //[일반 단어] 처리.
                //}-----------------

                if(FONT_Out_StyleMoonja(_bmp_, &_font, pX, pY, front_color, back_color, transparent, style, code,
                                        d_FONT_underline_no, true, 0, front_color,
                                        &moonja_width, &moonja_height) != true)
                {
                  return(false);

                }

              }

              //[문자] 출력 좌표 수정.
              pX += moonja_width;

          //}

        }

      }

  //}

  END:

  //[rLINEendindex 반환]
  //{
      //j 는 가장 마지막 문자위치 + 1 의 위치를 가지고 있으므로 이 값을 반환한다.
      (*rLINEendindex) = j;

  //}

  //[세로줄]
  //{
      //[2012.06.08.금][추가!!!]{---------------------------------------------------
      //이 <_EDITBUF_LINE_Out()> 함수는 모든 출력에서 [행출력] 에 사용되는 함수로
      //이 부분에서만 처리하면 모든 상황에서 반드시 처리된다.
      //
      //[2012.06.09.토][설명!!!]----------------------------------------------------
      //<_EditBuf_Text()> 도 내부적으로 <_EDITBUF_STRING_Out()> 함수를 사용하는데
      //이 <_EDITBUF_STRING_Out()> 함수 안에서 역시 <_EDITBUF_LINE_Out()> 함수로
      //처리하기 때문에 어떤 경우라도 반드시 이 함수를 거치게 되 있다.
      //단, <_EDITBUF_STRING_Out()> 의 경우 편집기가 최대 크기인 경우는 최대 [80행]
      //정도 처리하므로 80번을 반복할수 있으나 처리 속도가 빨라 편집에 전혀 영향을
      //주지 않는다.
      //
      //여기서는 [문자입력] 시나 행만 변하는 경우는 이 함수만 사용되므로 여기서는
      //항상 처리하는 것으로 하고, <_EDITBUF_STRING_Out()> 에서는 <_sw_VLine> 로
      //<_VLine()> 함수의 [동작 유/무] 를 결정하여 한번만 처리하는 것으로 한다.
      //}---------------------------------------------------------------------------
      
      if(_vLineEn == true) { _VLine(); }

  //}

  return(true);

}

bool __fastcall Teditor_edit_Form::_EDITBUF_STRING_Out(int  pX,
                                                       int  pY,
                                                       int  pLINEstartindex)
{
  //[2007.02.01.목][생성!!!]{------------------------------------------
  //FONT_Out_String2_withLINEstartINDEX() 함수를 대체하는 함수.
  //이는 [문법강조] 를 하기 위하여 _EDITBUF_LINE_Out() 함수를 사용하여
  //여러 행을 출력한다.
  //
  //[2009.04.01.수][중요수정!!!]---------------------------------------
  //처리할 내용이 저장소에 없는 경우는 처리하지 않는다.
  //
  //[2012.06.09.토][추가!!!]-------------------------------------------
  //[세로줄] 그리기 추가.
  //}------------------------------------------------------------------

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

      //[출력행계산관련]
      //{
          //현재 출력하는 문서의 행번호.
          int  line_number = 0;
          //출력 시작 행 번호(BASE:0)
          int  doc_line_start;
          //출력 끝 행 번호(BASE:0)
          int  doc_line_end;

      //}

  //}

  //[처리할 문서가 있나?]
  //{
      //[2009.04.01.수][추가!!!]{-------------------------------------------------------------
      //처리할 문서가 없는 경우는 아예 여기서 종료한다.
      //_MOONJACONFIG_LineGet() 함수로 [일반문서] 를 처리하는 경우 이전과 달리 단순한 방법을
      //사용했는데 이로 인하여 [색동문자] 구조체 정리가 달라져서 아래 문장을 추가 하지 않으면
      //계속 [무한반복] 에 들어 가게 된다.
      //따라서, 여기서 아예 처리할 내용이 없는 경우는 처리하지 않는다.
      //}-------------------------------------------------------------------------------------

      if(_editbuf[0] == '\0') return(true);

  //}

  //[출력행정보계산]
  //{
      //[설명!!!]{------------------------------------------------------------
      //출력 행의 범위를 계산한다.
      //여기서 "행" 은 "문서" 의 행을 말한다.(출력 영역의 행이 아니다.)
      //여기서 구한 두행 사이의 문서행만 실제로 출력하게 된다.
      //
      //[보정]----------------------------------------------------------------
      //[문서원점] 은 +2 의 offset 이 존재하므로 -2 해서 원래 값으로 돌려놓고
      //행을 계산해야 바른 값을 얻을수 있다.
      //}---------------------------------------------------------------------

      if(pY < 0)
      {
        //출력 시작 위치가 [음수] 인 경우, [음수 영역] 은 출력대상이 되지 않는다.

        //[출력 시작 행]
        doc_line_start = ((-1) * (pY - 2)) / _line_height;

        //[출력 끝 행]
        doc_line_end   = (_bmp_->Height - (pY - 2)) / _line_height;

      }
      else
      {
        //표시영역안은 항상 문서의 0 행부터 출력하면 된다.

        //[출력 시작 행]
        doc_line_start = 0;

        //[출력 끝 행]
        doc_line_end   = (_bmp_->Height - (pY - 2)) / _line_height;

      }

  //}

  //[세로줄:금지]
  //{
      //[2012.06.09.토][추가!!!]{-----------------------------------------------
      //이 함수의 실질적인 처리 함수인 <_EDITBUF_LINE_Out()> 함수에서
      //[세로줄] 이 처리되므로 중복되지 않도록 <_EDITBUF_LINE_Out()> 함수에서는
      //그리지 않도록 하고 이 함수 끝에서 한번만 직접 그려준다.
      //}-----------------------------------------------------------------------

      _sw_VLine = false;

  //}

  //[문자 출력]
  //{
      //[설명]{----------------------
      //전달받은 문자열을 출력한다.
      //CRLF : 행을 바꾸어 준다.
      //'\t' : [공백] 으로 처리한다.
      //}----------------------------

      //[출력위치계산]{----------------------
      //pX = 0 이되므로 pY 만 계산한다.
      pY += (doc_line_start * _line_height);
      line_number = doc_line_start;
      //}------------------------------------

      for(i = pLINEstartindex; ; )
      {
        //[행 출력]
        //{
            //현재 행을 출력한다.
            _EDITBUF_LINE_Out(pX, pY, i, &r_lineendindex);

        //}

        //[행 바꾸기]
        //{
            if((_editbuf[r_lineendindex] == 0x0d) && (_editbuf[r_lineendindex+1] == 0x0a))
            {
              //[!]{-------------------------------------------------------------------------
              //CRLF 의 경우 문자는 출력하지 않고 CRLF 도 2byte-code 로 전달하여 현재 글꼴의
              //출력 행의 높이 정보를 얻어 pY 위치만 수정한다.
              //}----------------------------------------------------------------------------

              //다음 행의 좌표로 수정한다.
              pX  = 0;
              pY += _line_height;

              i = (r_lineendindex + 2);

              //다음 행번호를 지정한다.
              line_number++;

              if(!(line_number <= doc_line_end))
              {
                //처리행을 넘었으므로 더이상 처리하지 않는다.
                break;//return(true);

              }

            }
            else if(_editbuf[r_lineendindex] == '\0')
            {
              //더이상 처리하지 않는다.
              break;//return(true);

            }

        //}

      }

  //}

  //[세로줄:허용:그리기]
  //{
      //[2012.06.09.토][추가!!!]{----------------------------
      //[세로줄] 을 허용하고 이 위치에서 [한번] 만 그려준다.
      //}----------------------------------------------------

      _sw_VLine = true;

      if(_vLineEn == true) { _VLine(); }

  //}

  return(true);

}

void __fastcall Teditor_edit_Form::_SELECTSCROLL_Up(int  pMOUSEy)
{
  //[2007.02.08.목][생성!!!]{----------------------------------------------------------------
  //[선택영역] 을 형성할때 [편집기] 위쪽을 넘는 경우는 자동으로 [줄이동] 을 해주어야 한다.

  //[2007.03.19.월][수정!!!]
  //[마우스] 로 [선택영역] 을 만드는 과정에서 [줄이동] 을 하는 경우를 위하여 직접 pMOUSEy 로
  //위치를 입력받아 처리하는 것으로 수정.
  //}----------------------------------------------------------------------------------------

  //[VAR]
  //{
      //현재 position 값.
      int  position = ide_editor_Form->_scroll_v_Form->_position;

  //}

  //[스크롤해야 하나?]
  //{
      //[입력지정자] 가 보이는 영역을 벗어 난 경우라면 윗줄로 스크롤한다.
      if(pMOUSEy < 0)
      {
        //[주의!!!]{--------------------------------------------------------------------------
        //여기서 [스크롤] 되는 경우는 _EDIT_V_Scroll() 함수 안에서 _EDIT_CaretPos() 함수가
        //처리 되어서는 안된다. 이렇게 하지 않으면 [입력지정자] 가 계속 위아래로 이동하는것이
        //보이므로 보기 좋지 않게 된다. (이 함수 마지막에 한번만 처리 되도록 한다.)
        //}-----------------------------------------------------------------------------------

        _edit_caretpos_on = false;
        //{
            //[마우스] 로 [선택영역] 을 만드는 과정에서 [줄이동] 을 하는 경우는
            //빠르게 [줄이동] 하기 위하여 3 줄씩 이동한다.
            position -= 3;

            ide_editor_Form->_scroll_v_Form->_Position(position);
        //}
        _edit_caretpos_on = true;

      }

  //}

  return;

}

void __fastcall Teditor_edit_Form::_SELECTSCROLL_Down(int  pMOUSEy)
{
  //[2007.02.08.목][생성!!!]{----------------------------------------------------------------
  //[선택영역] 을 형성할때 [편집기] 아래쪽을 넘는 경우는 자동으로 [줄이동] 을 해주어야 한다.

  //[2007.03.19.월][수정!!!]
  //[마우스] 로 [선택영역] 을 만드는 과정에서 [줄이동] 을 하는 경우를 위하여 직접 pMOUSEy 로
  //위치를 입력받아 처리하는 것으로 수정.
  //}----------------------------------------------------------------------------------------

  //[VAR]
  //{
      //현재 position 값.
      int  position      = ide_editor_Form->_scroll_v_Form->_position;

  //}

  //[스크롤해야 하나?]
  //{
      //[입력지정자] 가 보이는 영역을 벗어 난 경우라면 아랫줄로 스크롤한다.
      if(pMOUSEy > (this->Height - editor_info_Form->Height))
      {
        _edit_caretpos_on = false;
        //{
            //[마우스] 로 [선택영역] 을 만드는 과정에서 [줄이동] 을 하는 경우는
            //빠르게 [줄이동] 하기 위하여 3 줄씩 이동한다.
            position += 3;

            ide_editor_Form->_scroll_v_Form->_Position(position);
        //}
        _edit_caretpos_on = true;

      }

  //}

  return;

}

void __fastcall Teditor_edit_Form::_SELECTSCROLL_Left(int  pMOUSEx)
{
  //[2007.02.08.목][생성!!!]{----------------------------------------------------------------
  //[선택영역] 을 형성할때 [편집기] 왼쪽을 넘는 경우는 자동으로 [줄이동] 을 해주어야 한다.

  //[2007.03.19.월][수정!!!]
  //[마우스] 로 [선택영역] 을 만드는 과정에서 [줄이동] 을 하는 경우를 위하여 직접 pMOUSEx 로
  //위치를 입력받아 처리하는 것으로 수정.
  //}----------------------------------------------------------------------------------------

  //[VAR]
  //{
      //현재 position 값.
      int  position      = ide_editor_Form->_scroll_h_Form->_position;

  //}

  //[스크롤해야 하나?]
  //{
      //[입력지정자] 가 보이는 영역을 벗어 난 경우라면 왼쪽으로 스크롤한다.

      //[2007.04.10.화][수정!!!]{-----------------------------------------
      //단, 이미 왼쪽끝에 와 있는 상태라면 처리하지 않아야 한다.
      //이는 아래 _Position() 함수로 줄이동 하는 경우 해당 처리부에서
      //_EditBuf_Text() 함수가 중복 처리 되어 깜박임이 발생하기 때문이다.
      //}-----------------------------------------------------------------

      if((pMOUSEx < d_gutter_width) && (position > 0))
      {
        //[한글/영문?]
        //{
            //[!]{-----------------------------------------------------------------------------------------
            //현재 _caretindex 위치의 문자가 [한글/영문] 에 따라 스크롤 값이 달라야 한다.
            //위에서 이미 _caretindex 에 해당하는 문자를 건너서 이동한 것이므로 이 폭을가지고 따져야 한다.
            //}--------------------------------------------------------------------------------------------

            if     (_editbuf[_caretindex] > 0)
            {
              //[영문] 인 경우는 [영문폭] 로 이동해야 하므로 -1 만큼 스크롤 한다.
              position -= 1;

            }
            else if(_editbuf[_caretindex] < 0)
            {
              //[한글] 인 경우는 [영문폭*2] 로 이동해야 하므로 -2 만큼 스크롤 한다.
              position -= 2;

            }

        //}

        //지정 양만큼 수평으로 스크롤 한다.
        ide_editor_Form->_scroll_h_Form->_Position(position);

      }

  //}

  return;

}

void __fastcall Teditor_edit_Form::_SELECTSCROLL_Right(int  pMOUSEx)
{
  //[2007.02.08.목][생성!!!]{----------------------------------------------------------------
  //[선택영역] 을 형성할때 [편집기] 오른쪽을 넘는 경우는 자동으로 [줄이동] 을 해주어야 한다.

  //[2007.03.19.월][수정!!!]
  //[마우스] 로 [선택영역] 을 만드는 과정에서 [줄이동] 을 하는 경우를 위하여 직접 pMOUSEx 로
  //위치를 입력받아 처리하는 것으로 수정.
  //}----------------------------------------------------------------------------------------

  //[VAR]
  //{
      //현재 position 값.
      int  position        = ide_editor_Form->_scroll_h_Form->_position;

      int  caretindex_save = _caretindex;

  //}

  //[스크롤해야 하나?]
  //{
      //[입력지정자] 가 보이는 영역을 벗어 난 경우라면 왼쪽으로 스크롤한다.
      if(pMOUSEx > (this->Width - ide_editor_Form->_scroll_v_Form->Width))
      {
        //[한글/영문?]
        //{
            //[!]{----------------------------------------------------------------------------------------------
            //현재 _caretindex 위치의 문자가 [한글/영문] 에 따라 스크롤 값이 달라야 한다.
            //위에서 이미 _caretindex 에 해당하는 문자를 건너서 이동한 것이므로 이동하기 전의  위치로 검사한다.
            //}-------------------------------------------------------------------------------------------------

            if     (_editbuf[caretindex_save] > 0)
            {
              //[영문] 인 경우는 [영문폭] 로 이동해야 하므로 +1 만큼 스크롤 한다.
              position += 1;

            }
            else if(_editbuf[caretindex_save] < 0)
            {
              //[한글] 인 경우는 [영문폭*2] 로 이동해야 하므로 +2 만큼 스크롤 한다.
              position += 2;

            }
        //}

        //지정 양만큼 수평으로 스크롤 한다.
        ide_editor_Form->_scroll_h_Form->_Position(position);

      }

  //}

  return;

}

bool __fastcall Teditor_edit_Form::_CARET_ViewAlways(//[2009.05.09.토][추가!!!]
                                                     //실제 적용하지 않고 확인만 하는 경우는 true.
                                                     bool  pSimulate)
{
  //[2007.02.24.토][생성!!!]{-----------------------------------------------------------------
  //어떤 상황에서도 [입력지정자] 가 이동하는 경우는 항상 [편집기] 상에서 눈에
  //보이는위치에 있도록 자동으로 [수평/수직 줄이동] 을 해준다.
  //현재 [입력지정자] 의 위치가 눈에 보이지 않는 위치에 있다면 [줄이동] 만으로
  //간단하게 눈에 보이는 위치에 있도록 만들수 있다.

  //[2007.02.28.수][수정!!!]
  //두개의 [줄이동] 이 동시에 처리되는 경우는 _EditBuf_Text() 함수가 한번만
  //실행될수 있도록 _editbuf_text_on 상태를 조정하여 준다.
  //이를 위하여 _Position() 함수를 바로 사용하지 않고 먼저 값을 구한뒤 일괄 처리한다.

  //[2007.03.10.토][수정!!!]
  //경우에 해당되어 이 함수를 처리한 경우는 true 를 반환하여 처리 했다는 것을 알린다.
  //이는 중복으로 새로 그려지는 것을 막아서 깜박거림을 방지하기 위한 것이다.

  //[2007.03.11.일][수정!!!]
  //_KEY_Left() 등 함수를 수행할때 이 함수가 먼저 호출되는데, 이때는 정확하게 [입력지정자]
  //가 화면의 가장 왼쪽에 있게 된다. 이 후 _KEY_Left() 가 호출되면 다시 한번 한칸 왼쪽으로
  //이동하게 되므로 결과적으로 두번 왼쪽으로 [줄이동] 하는 셈이 되어 동작이 구분되어 보이므로
  //보기 좋지 않다.
  //이것을 막기 위하여 아예 _CARET_ViewAlways() 함수에서 1줄, 1칸씩 여유를 더 준다.
  //이 경우, 이미 1칸 여유가 있으므로 _KEY_Left() 에서는 이미 이동을 해도 [입력지정자] 가
  //보이는 위치에 있으므로 [줄이동] 을 하지 않아서 문제가 말끔하게 해결된다.
  //}-----------------------------------------------------------------------------------------

  //[방법]{---------------------------------------------------------------------
  //[줄이동자] 의 _position 값이 [수직] 인 경우는] 가장 윗줄의 행번호가 되고,
  //[수평] 인 경우는 [영문자 폭] 을 기준으로 한 열번호가 된다.
  //따라서, _position 값을 구해진 값으로 직접 수정하여 [입력지정자] 가 보이도록
  //[줄이동] 한다.
  //
  //수직/수평을 별도로 분리 처리한다.(순서대로 처리)
  //
  //[주의!!!]-------------------------------------------------------------------
  //수평의 경우는 정확하게 [줄이동] 을 할수 없으므로 [영문자폭] 1 개 단위정도
  //여유를 두어서 처리하는 것이 좋다.
  //}---------------------------------------------------------------------------

  //[VAR]
  //{
      //현재 [줄이동자] 의 _position 값을 기록한다.
      int   scroll_v_position;
      int   scroll_h_position;

      //해당 [줄이동] 을 해야 하는 경우는 true 로 설정.
      bool  scroll_v_use = false;
      bool  scroll_h_use = false;

      //[수직 줄이동] 관련 처리정보.
      int   gap_y     = 0,
            gap_y_row = 0;

      //[수평 줄이동] 관련 처리정보.
      int   gap_x     = 0,
            gap_x_col = 0;

  //}

  //[스크롤정보얻기]
  //{
      scroll_v_position = ide_editor_Form->_scroll_v_Form->_position;
      scroll_h_position = ide_editor_Form->_scroll_h_Form->_position;

  //}

  //[수평검사]
  //{
      if     ((_caret_x + (_text_org_x + 2 - 1)) < d_gutter_width)
      {
        //[!]{----------------------------------------------------------------------------------
        //[입력지정자] 가 [편집기] 왼쪽으로 사라져 있는 상태.
        //이 경우는 [입력지정자] 가 [편집기] 가장 왼쪽에 위치하도록 [수평줄이동] 해주어야 한다.
        //}-------------------------------------------------------------------------------------

        //[행수 구하기]
        //{
            //벗어난 길이를 구한다.
            gap_x     = d_gutter_width - (_caret_x + (_text_org_x + 2 - 1));

            //기본적으로 열 1 개는 추가한다.(이미 보이지 않는 영역에 있으므로)
            //1 개더 여유를 준다.---------------------v
            gap_x_col = gap_x / _font_eng_width + 1 + 1;

        //}

        //[줄이동]
        //{
            //[입력지정자] 가 가장 왼쪽열에 위치하도록 [수평줄이동] 한다.
            scroll_h_use       = true;
            //_position 값을 구한다.
            scroll_h_position -= gap_x_col;

        //}

      }
      else if((_caret_x + (_text_org_x + 2 - 1)) > (this->Width - ide_editor_Form->_scroll_v_Form->Width))
      {
        //[!]{------------------------------------------------------------------------------------
        //[입력지정자] 가 [편집기] 오른쪽으로 사라져 있는 상태.
        //이 경우는 [입력지정자] 가 [편집기] 가장 오른쪽에 위치하도록 [수평줄이동] 해주어야 한다.
        //}---------------------------------------------------------------------------------------

        //[행수 구하기]
        //{
            //벗어난 길이를 구한다.
            gap_x     = ((_caret_x + (_text_org_x + 2 - 1)) - (this->Width - ide_editor_Form->_scroll_v_Form->Width));

            //기본적으로 열 1 개는 추가한다.(이미 보이지 않는 영역에 있으므로)
            //1 개더 여유를 준다.---------------------v
            gap_x_col = gap_x / _font_eng_width + 1 + 1;
        //}

        //[줄이동]
        //{
            //[입력지정자] 가 가장 아랫줄에 위치하도록 [수직줄이동] 한다.
            scroll_h_use       = true;
            //_position 값을 구한다.
            scroll_h_position += gap_x_col;

        //}

      }

  //}

  //[수직검사]
  //{
      if     ((_caret_y + (_text_org_y + 2 - 1)) < 0)
      {
        //[!]{----------------------------------------------------------------------------------
        //[입력지정자] 가 [편집기] 위로 사라져 있는 상태.
        //이 경우는 [입력지정자] 가 [편집기] 가장 윗쪽에 위치하도록 [수직줄이동] 해주어야 한다.
        //-(_caret_y + (_text_org_y + 2)) 값은 가장 작은 것이 8 이 된다.
        //즉, 행의 높이보다 작다. 그러나 [줄이동] 은 해 주어야 한다.
        //따라서, 0 이 아닌 값의 경우도 무조건 1 개의 행으로 보고 기본적으로 한줄은
        //[줄이동] 을 해준다.
        //}-------------------------------------------------------------------------------------

        //[행수 구하기]
        //{
            //벗어난 길이를 구한다.
            gap_y     = -(_caret_y + (_text_org_y + 2 - 1));

            //기본적으로 행 1 개는 추가한다.(이미 보이지 않는 영역에 있으므로)
            //1 개더 여유를 준다.------------------v
            gap_y_row = gap_y / _line_height + 1 + 1;

        //}

        //[줄이동]
        //{
            //[입력지정자] 가 가장 윗줄에 위치하도록 [수직줄이동] 한다.
            scroll_v_use       = true;
            //_position 값을 구한다.
            scroll_v_position -= gap_y_row;

        //}

      }
      else if((_caret_y + (_text_org_y + 2 - 1)) > (this->Height - editor_info_Form->Height -
                                                    //[2009.05.06.수][중요추가!!!]
                                                    //행 한개 정도 여유있게 처리한다.
                                                    _line_height))
      {
        //[!]{------------------------------------------------------------------------------------
        //[입력지정자] 가 [편집기] 아래로 사라져 있는 상태.
        //이 경우는 [입력지정자] 가 [편집기] 가장 아래쪽에 위치하도록 [수직줄이동] 해주어야 한다.
        //((_caret_y + (_text_org_y + 2)) - (this->Height - editor_info_Form->Height)) 값은
        //가장 작은 것이 8 이 된다.
        //즉, 행의 높이보다 작다. 그러나 [줄이동] 은 해 주어야 한다.
        //따라서, 0 이 아닌 값의 경우도 무조건 1 개의 행으로 보고 기본적으로 한줄은
        //[줄이동] 을 해준다.
        //}---------------------------------------------------------------------------------------

        //[행수 구하기]
        //{
            //벗어난 길이를 구한다.
            gap_y     = ((_caret_y + (_text_org_y + 2 - 1)) - (this->Height - editor_info_Form->Height -
                                                               //[2009.05.06.수][중요추가!!!]
                                                               //행 한개 정도 여유있게 처리한다.
                                                               _line_height));

            //기본적으로 행 1 개는 추가한다.(이미 보이지 않는 영역에 있으므로)
            //1 개더 여유를 준다.------------------v
            gap_y_row = gap_y / _line_height + 1 + 1;

        //}

        //[줄이동]
        //{
            //[입력지정자] 가 가장 아랫줄에 위치하도록 [수직줄이동] 한다.
            scroll_v_use       = true;

            //_position 값을 구한다.
            scroll_v_position += gap_y_row;

        //}

      }

  //}

  //[실제 줄이동]
  //{
      //[2007.02.28.수][수정!!!]{----------------------------------------------------------------
      //구해 놓은 값으로 실제 [줄이동] 한다.
      //단, [수평/수직] 둘다 [줄이동] 하는 경우는 _EditBuf_Text() 함수가 한번만 실행하게 만든다.
      //}----------------------------------------------------------------------------------------

      if     ((scroll_h_use == true) && (scroll_v_use == true))
      {
        //둘다 [줄이동] 하는 경우는 _EditBuf_Text() 가 두번 중복 처리되는 것을 막기 위하여
        //한번만 처리 하도록 처리한다.

        if(pSimulate == false)
        {
          //[2009.05.09.토][추가!!!]{------
          //실제 적용하는 경우만 처리한다.
          //}------------------------------

          _editbuf_text_on = false;
          //{
              //[수평줄이동] 시에는 _EditBuf_Text() 함수를 처리하지 않는다.
              ide_editor_Form->_scroll_h_Form->_Position(scroll_h_position);
          //}
          _editbuf_text_on = true;

          ide_editor_Form->_scroll_v_Form->_Position(scroll_v_position);

        }

        return(true);

      }
      else if(scroll_h_use == true)
      {
        if(pSimulate == false)
        {
          //[2009.05.09.토][추가!!!]{------
          //실제 적용하는 경우만 처리한다.
          //}------------------------------

          //[수평줄이동] 만 하는 경우.
          ide_editor_Form->_scroll_h_Form->_Position(scroll_h_position);

        }

        return(true);

      }
      else if(scroll_v_use == true)
      {
        if(pSimulate == false)
        {
          //[2009.05.09.토][추가!!!]{------
          //실제 적용하는 경우만 처리한다.
          //}------------------------------

          //[수직줄이동] 만 하는 경우.
          ide_editor_Form->_scroll_v_Form->_Position(scroll_v_position);

        }

        return(true);

      }
      
  //}

  //현재 [입력지정자] 가 눈에 보이는 위치에 있으므로 이 함수를 처리하지 않은 것이다.
  return(false);

}

bool __fastcall Teditor_edit_Form::_Caret_ViewAlways_Middle(//항상 위쪽도 중간위 위치.
                                                            bool  pAlwaysTopMiddle,
                                                            //항상 아래쪽도 중간에 위치.
                                                            bool  pAlwaysBottomMiddle)
{
  //[2009.05.08.토][생성!!!]{-----------------------------------------------------------------------
  //_CARET_ViewAlways() 함수를 기본으로 하되 항상 편집기 보이는 영역의 중간에
  //위치 하도록 처리한다.
  //[수평] 은 원래 그대로 처리한다.
  //<pAlwaysMiddle : true>  : [입력지정자] 가 이미 보이는 영역에 있더라도 무조건 중간에 위치시킨다.
  //                          이는 아래/위 모두 해당한다.
  //<pAlwaysMiddle : false> : [입력지정자] 가 이미 보이는 영역에 있다면 아래쪽에만 여유를 둔다.
  //                          위쪽은 그대로 두고 아래쪽은 여유를 준다.
  //}-----------------------------------------------------------------------------------------------

  //[VAR]
  //{
      //현재 [줄이동자] 의 _position 값을 기록한다.
      int   scroll_v_position;
      int   scroll_h_position;

      //해당 [줄이동] 을 해야 하는 경우는 true 로 설정.
      bool  scroll_v_use = false;
      bool  scroll_h_use = false;

      //[수직 줄이동] 관련 처리정보.
      int   gap_y     = 0,
            gap_y_row = 0;

      //[수평 줄이동] 관련 처리정보.
      int   gap_x     = 0,
            gap_x_col = 0;

      //[편집기] 상의 눈에 보이는 영역의 행 수.
      int   viewLineCount;

      //보이는 영역의 가장 위 행번호.
      int   lineTopNumber;

      //보이는 영역의 가장 아래 행번호.
      int   lineBottomNumber;

  //}

  //[스크롤정보얻기]{---------------------------------------------
  scroll_v_position = ide_editor_Form->_scroll_v_Form->_position;
  scroll_h_position = ide_editor_Form->_scroll_h_Form->_position;
  //}-------------------------------------------------------------

  //[수평검사]
  //{
      if     ((_caret_x + (_text_org_x + 2 - 1)) < d_gutter_width)
      {
        //[!]{----------------------------------------------------------------------------------
        //[입력지정자] 가 [편집기] 왼쪽으로 사라져 있는 상태.
        //이 경우는 [입력지정자] 가 [편집기] 가장 왼쪽에 위치하도록 [수평줄이동] 해주어야 한다.
        //}-------------------------------------------------------------------------------------

        //[행수 구하기]
        //{
            //벗어난 길이를 구한다.
            gap_x     = d_gutter_width - (_caret_x + (_text_org_x + 2 - 1));

            //기본적으로 열 1 개는 추가한다.(이미 보이지 않는 영역에 있으므로)
            //1 개더 여유를 준다.---------------------v
            gap_x_col = gap_x / _font_eng_width + 1 + 1;

        //}

        //[줄이동]
        //{
            //[입력지정자] 가 가장 왼쪽열에 위치하도록 [수평줄이동] 한다.
            scroll_h_use       = true;
            //_position 값을 구한다.
            scroll_h_position -= gap_x_col;

        //}

      }
      else if((_caret_x + (_text_org_x + 2 - 1)) > (this->Width - ide_editor_Form->_scroll_v_Form->Width))
      {
        //[!]{------------------------------------------------------------------------------------
        //[입력지정자] 가 [편집기] 오른쪽으로 사라져 있는 상태.
        //이 경우는 [입력지정자] 가 [편집기] 가장 오른쪽에 위치하도록 [수평줄이동] 해주어야 한다.
        //}---------------------------------------------------------------------------------------

        //[행수 구하기]
        //{
            //벗어난 길이를 구한다.
            gap_x     = ((_caret_x + (_text_org_x + 2 - 1)) - (this->Width - ide_editor_Form->_scroll_v_Form->Width));

            //기본적으로 열 1 개는 추가한다.(이미 보이지 않는 영역에 있으므로)
            //1 개더 여유를 준다.---------------------v
            gap_x_col = gap_x / _font_eng_width + 1 + 1;
        //}

        //[줄이동]
        //{
            //[입력지정자] 가 가장 아랫줄에 위치하도록 [수직줄이동] 한다.
            scroll_h_use       = true;
            //_position 값을 구한다.
            scroll_h_position += gap_x_col;

        //}

      }

  //}


  //[행정보 얻기]
  //{
      //[편집기] 의 보여지는 영역의 전체 행수를 구한다.
      viewLineCount    = (this->Height - editor_info_Form->Height) / _line_height;

      //가장 위 행번호.(항상 관리되고 있는 정보를 사용한다.)
      lineTopNumber    = _linetop_linenumber;

      //가장 아래 행번호.
      lineBottomNumber = lineTopNumber + viewLineCount - 2;

  //}


  //[수직검사]
  //{
      //[위쪽] 처리.
      if     ((_caret_y + (_text_org_y + 2 - 1)) < 0)
      {
        //[!]{----------------------------------------------------------------------------------
        //[입력지정자] 가 [편집기] 위로 사라져 있는 상태.
        //이 경우는 [입력지정자] 가 [편집기] 가장 윗쪽에 위치하도록 [수직줄이동] 해주어야 한다.
        //-(_caret_y + (_text_org_y + 2)) 값은 가장 작은 것이 8 이 된다.
        //즉, 행의 높이보다 작다. 그러나 [줄이동] 은 해 주어야 한다.
        //따라서, 0 이 아닌 값의 경우도 무조건 1 개의 행으로 보고 기본적으로 한줄은
        //[줄이동] 을 해준다.
        //}-------------------------------------------------------------------------------------

        //[행수 구하기]
        //{
            if(pAlwaysTopMiddle == true)
            {
              //벗어난 길이를 구한다.
              //무조건 중간에 위치하게 만든다.
              gap_y = -((_caret_y + (_text_org_y + 2 - 1)) - ((_line_height * viewLineCount)/2));

            }
            else
            {
              //벗어난 길이를 구한다.
              //단지 보이는 영역이면 충분하다.
              gap_y = -(_caret_y + (_text_org_y + 2 - 1));

            }

            gap_y_row = gap_y / _line_height + 1;

        //}

        //[줄이동]
        //{
            //[입력지정자] 가 가장 윗줄에 위치하도록 [수직줄이동] 한다.
            scroll_v_use       = true;
            //_position 값을 구한다.
            scroll_v_position -= gap_y_row;

        //}

      }
      //[아래쪽] 처리.
      else if((_caret_y + (_text_org_y + 2 - 1)) > (this->Height - editor_info_Form->Height -
                                                    //[2009.05.06.수][중요추가!!!]
                                                    //행 한개 정도 여유있게 처리한다.
                                                    _line_height))
      {
        //[!]{------------------------------------------------------------------------------------
        //[입력지정자] 가 [편집기] 아래쪽으로 사라진 경우는 보이는 가장 아래에 위치시킨다.
        //이 경우는 [입력지정자] 가 [편집기] 가장 아래쪽에 위치하도록 [수직줄이동] 해주어야 한다.
        //((_caret_y + (_text_org_y + 2)) - (this->Height - editor_info_Form->Height)) 값은
        //가장 작은 것이 8 이 된다.
        //즉, 행의 높이보다 작다. 그러나 [줄이동] 은 해 주어야 한다.
        //따라서, 0 이 아닌 값의 경우도 무조건 1 개의 행으로 보고 기본적으로 한줄은
        //[줄이동] 을 해준다.
        //}---------------------------------------------------------------------------------------

        //[행수 구하기]
        //{
            if(pAlwaysBottomMiddle == true)
            {
              //벗어난 길이를 구한다.
              //중간즘에 여유있게 위치 시킨다.
              gap_y = ((_caret_y + (_text_org_y + 2 - 1)) - (this->Height - editor_info_Form->Height -
                                                             //[2009.05.06.수][중요추가!!!]
                                                             //행 한개 정도 여유있게 처리한다.
                                                             _line_height - ((_line_height * viewLineCount)/2)));

            }
            else
            {
              //벗어난 길이를 구한다.
              //단지 보이는 영역에 있으면 된다.
              gap_y = ((_caret_y + (_text_org_y + 2 - 1)) - (this->Height - editor_info_Form->Height -
                                                             //[2009.05.06.수][중요추가!!!]
                                                             //행 한개 정도 여유있게 처리한다.
                                                             _line_height));

            }

            gap_y_row = gap_y / _line_height + 1;

        //}

        //[줄이동]
        //{
            //[입력지정자] 가 가장 아랫줄에 위치하도록 [수직줄이동] 한다.
            scroll_v_use       = true;

            //_position 값을 구한다.
            scroll_v_position += gap_y_row;

        //}

      }

  //}

  //[실제 줄이동]
  //{
      //[2007.02.28.수][수정!!!]{----------------------------------------------------------------
      //구해 놓은 값으로 실제 [줄이동] 한다.
      //단, [수평/수직] 둘다 [줄이동] 하는 경우는 _EditBuf_Text() 함수가 한번만 실행하게 만든다.
      //}----------------------------------------------------------------------------------------

      if     ((scroll_h_use == true) && (scroll_v_use == true))
      {
        //둘다 [줄이동] 하는 경우는 _EditBuf_Text() 가 두번 중복 처리되는 것을 막기 위하여
        //한번만 처리 하도록 처리한다.

        _editbuf_text_on = false;
        //{
            //[수평줄이동] 시에는 _EditBuf_Text() 함수를 처리하지 않는다.
            ide_editor_Form->_scroll_h_Form->_Position(scroll_h_position);
        //}
        _editbuf_text_on = true;

        ide_editor_Form->_scroll_v_Form->_Position(scroll_v_position);

        return(true);

      }
      else if(scroll_h_use == true)
      {
        //[수평줄이동] 만 하는 경우.
        ide_editor_Form->_scroll_h_Form->_Position(scroll_h_position);

        return(true);

      }
      else if(scroll_v_use == true)
      {
        //[수직줄이동] 만 하는 경우.
        ide_editor_Form->_scroll_v_Form->_Position(scroll_v_position);

        return(true);

      }

  //}

  //현재 [입력지정자] 가 눈에 보이는 위치에 있으므로 이 함수를 처리하지 않은 것이다.
  return(false);

}

void __fastcall Teditor_edit_Form::_EDIT_SelectDelete(void)
{
  //[2007.03.07.수][생성!!!]{----------------------------------------
  //[삭제] 는 <Del-Key> 로 처리한다.
  //단, [선택영역] 이 없는 경우는 처리하지 않아야 한다.
  //이 함수는 [간편기능목록] 에서 [삭제] 항목을 처리하는데 사용된다.
  //}----------------------------------------------------------------

  //[VAR]
  //{
      struct CARETINFO   select_start;
      struct CARETINFO   select_end;

  //}

  //[선택영역 존재 확인]
  //{
      //[선택영역] 이 없는 경우는 바로 종료한다.
      if(_SELECT_Get_StartEndIndex(&select_start, &select_end) != true) return;

  //}

  //[수정이력][2009.05.03.일][추가!!!]{*****************
  //[수정이력] 은 _KEY_Delete() 함수에서 자동 처리된다.
  //}***************************************************

  //[선택영역 삭제]{---
  _KEY_Delete(true);
  //}------------------

}

void __fastcall Teditor_edit_Form::_EDIT_Paste(char *pPASTEstr,
                                               //[2009.05.07.목][추가!!!]
                                               //다시그리는 경우는 true.
                                               bool   pReDraw)
{
  //[2007.03.07.수][생성!!!]{-------------------------------------------------------------
  //전달받은 문자열을 _editbuf[] 의 현재 [입력지정자] 위치에 붙여넣고,
  //수정된 내용의 반영을 위하여 _EditBuf_Text() 함수로 다시 한번 출력한다.
  //
  //[붙여넣기] 는 [문서] 를 관리하는 정보의 전체적인 수정이 가해진다.
  //이 함수는 [간편기능목록] 에서 [붙이기] 항목을 처리하는데 사용된다.
  //
  //CRLF 를 얻어서 행수를 STR_Get_CRLF_Count_withStartEndIndex() 함수를 사용하여
  //구한다음 해당 관리변수(_line_count)도 수정해 주어야 한다.

  //[2007.03.20.화][수정!!!]--------------------------------------------------------------
  //이미 [선택영역] 이 있는 경우는 이 [선택영역] 을 삭제하고 내용을 [붙여넣기] 해야 한다.
  //1) [선택영역] 을 삭제한다.(이때 [입력지정자] 는 [선택영역] 시작위치에 있는 상태)
  //2) 현 [입력지정자] 위치에 지정 문자열을 끼워넣는다.
  //
  //[2012.05.24.목][수정!!!]--------------------------------------------------------------
  //}-------------------------------------------------------------------------------------

  //[VAR]
  //{
      int  i;

      //전달받은 문자열의 길이.('\0' 은 제외한 길이)
      int  size;

      int  crlf_count = 0;

      //[2007.03.20.화][추가!!!]
      struct CARETINFO  select_start;
      struct CARETINFO  select_end;

      //_CARET_ViewAlways() 함수가 내부적으로 동작한 경우 true 로 된다.
      bool   caretAlwaysView = false;
      bool   select_use      = false;

      //[2012.06.11.월][추가!!!]
      //<_CommentBlock_Info()> 의 결과를 보관.
      bool   cmtBlkChanged = false;

  //}

//[2012.05.31.목][임시문장]
//msg_msg_Form->_PrintAddLine(0, "_EDIT_Paste");

  //[<Shift> 해제]
  //{
      //[2007.02.27.화][추가!!!]{----------------------------------------------------
      //<Shift> 는 문자 입력시 무효하므로 [선택영역] 의 해제를 위하여 기록을 지운다.
      //이렇게 하는 이유는 _EDIT_CaretPos() 함수안의 [선택영역] 처리부분을 참고한다.
      //}----------------------------------------------------------------------------

      _shift_down = false;

  //}

  //[선택영역 처리]
  //{
      //[설명]{-----------------------------------------------
      //[2007.02.13.화]
      //1. 일단 [선택영역] 구간을 _editbuf[] 상에서 삭제한다.
      //2. [붙이기] 동작을 처리한다.
      //}-----------------------------------------------------

      //먼저 [입력지정자] 의 위치를 [선택영역] 시작 지점으로 이동시킨다.
      if(_SELECT_Get_StartEndIndex(&select_start, &select_end) != true) goto PASTE;


      //[수정이력][2009.05.03.일][추가!!!]{************************
      //[선택영역] 은 여기서 [삭제] 되므로 이를 기록한다.
      //[선택영역] 은 항상 관리 상태이므로 간단하게 처리 가능하다.
      //[수집 시작 위치]-------------------------------------------
      _history.strStartIndex = select_start.caret_index;
      //[수집 끝 위치]---------------------------------------------
      _history.strEndIndex   = select_end.caret_index;
      //[수집]-----------------------------------------------------
      //[삭제] 수정이다.
      History_Add('-', 's');
      //}**********************************************************


      //[입력지정자 위치 수정]
      //{
          //[선택영역] 이 있는 경우만 처리한다.
          //[입력지정자] 위치는 select_startindex 위치가 된다.(작은 index)
          _caretindex = select_start.caret_index;
          _caret_x    = select_start.caret_x;
          _caret_y    = select_start.caret_y;

          //[입력지정자 위치 조정]
          _EDIT_CaretPos(_caret_x, _caret_y);

      //}

      //[입력지정자 항상 보이기]
      //{
          _editbuf_text_no = true;
          //{
              //키는 항상 눈에 보이는 위치에 있어야 한다.
              caretAlwaysView = _CARET_ViewAlways(false);
              //<키> 를 처리하지 않고 여기서 종료 되므로 이곳에서 한번 실행해 주어야 한다.
          //}
          _editbuf_text_no = false;

      //}

      //[선택영역 정보 복구]
      //{
          //위에서 처리한 _EDIT_CaretPos() 에서 해제된 [선택영역] 의 정보를 다음 처리부에서
          //삭제할수 있도록 이미 얻어 놓은 정보로 복구한다.
          _select_start = select_start;
          _select_end   = select_end;

      //}

      //[선택영역] 삭제.
      if(_SELECT_Delete(&select_start, &crlf_count) == true)
      {
        //[선택영역] 을 처리했다는 것을 알린다.
        select_use = true;

        //[행수 수정]
        //{
            //CRLF 가 삭제된 것이 있는 경우만 수정한다.
            if(crlf_count > 0) { _linecount -= crlf_count; }

        //}

        //[묶음주석 정보 수집]
        //{
            //[2012.06.10.일][추가!!!]{---------------
            //반드시 [수정] 된 후에 [수집] 해야 한다.
            //}---------------------------------------

            //계속 이어지므로 여기서는 처리하지 않는다.
            //[2012.06.12.화][수정!!!]
            //부분정보 수집----------------------v
            //cmtBlkChanged = _CommentBlock_Info(true);

        //}

        //[삭제 반영]{----------------------------------------------------------------------
        //이 문자키의 경우는 한줄만 다시 그려지므로 여기서 처리하지 않으면
        //삭제된 내용이 반영되지 않는다.(반드시 여기서 처리한다)
        //_EditBuf_Text();
        //[2007.03.10.토][수정!!!]
        //여기서 처리 하지 않고 중복 처리를 방지하기 위하여 이 함수 끝에서 한번만 처리한다.
        //}---------------------------------------------------------------------------------

        //[수직스크롤설정]
        //{
            //[!]{----------------------------------------------------------------
            //수정된 행이 있는 경우는 문서행수가 바뀌었으므로 [수직스크롤] 을
            //새로 설정해 주어야 한다.
            //일반 키입력시에는 행이 바뀌지 않으므로 행이 바뀐 이곳에서 처리한다.
            //}-------------------------------------------------------------------

            if(crlf_count > 0) { _Scroll_Resize(); }

        //}

      }

      goto CONTINUE;
      
  //}

  //[순수한 "붙이기" 처리]------------------------------------------------------

  PASTE:

  //[입력지정자 항상 보이기]
  //{
      //_EditBuf_Text() 함수가 중복 처리 되는 것을 막기 위한것이다.
      //이 함수 끝에서 한번만 직접 처리하게 만든다.
      _edit_paste_ing = true;
      //{
          //키는 항상 눈에 보이는 위치에 있어야 한다.
          //[주의!!!]
          //문서가 수정되기 전에 미리 해 주어야 정확하게 동작한다.
          caretAlwaysView = _CARET_ViewAlways(false);

      //}
      _edit_paste_ing = false;

  //}

  CONTINUE:


  //[수정이력][2009.05.03.일][추가!!!]{**************************
  //[수집] 시작 위치를 기록한다.
  //[수집 시작 위치]---------------------------------------------
  _history.strStartIndex = _caretindex;
  //}************************************************************


  //[문자열 크기 얻기]
  //{
      size = strlen(pPASTEstr);

  //}

  //[포함된 행수 구하기]
  //{
      crlf_count = STR_Get_CRLF_Count_withStartEndIndex(pPASTEstr, 0, size - 1);

  //}

  //[공간 만들기]
  //{
      //[2007.04.09.월][수정!!!]{------------------------------------------------------
      //for() 문을 사용하여 공간을 만드는 것은 문서량이 많은 경우 시간이 많이 걸리므로
      //_tempbuf[] 와 memmove() 함수를 사용하여 복사 방식으로 처리한다.
      //}------------------------------------------------------------------------------

      //끼워 넣을 시작위치부터 문서끝까지의 문자열을 _tempbuf[] 에 대피시킨다.
      memmove(_tempbuf, &(_editbuf[_caretindex]), _filesize - _caretindex);

      //끼워넣을 공간 다음에 다시 복사해서 붙여준다.
      memmove(&(_editbuf[_caretindex + size]), _tempbuf, _filesize - _caretindex);

      /*
      //[밀어내기] 의 경우는 memmove() 를 사용할수 없으므로 for() 문으로 일일히
      //복사하는 방법을 사용한다.
      for(i = _filesize; i >= _caretindex; i--)
      {
        //집어 넣을 문자열의 길이 만큼 공간을 만들어야 하므로 문자열의 길이만큼의 거리에 복사한다.
        _editbuf[i + size] = _editbuf[i];

      }
      */
  //}

  //[끼워넣기]
  //{
      //비워진 공간에 전달받은 문자열을 끼워 넣는다.
      //memmove() 를 사용하여 고속으로 [복사] 한다.
      memmove(&(_editbuf[_caretindex]), pPASTEstr, size);

  //}

  //[수정이력][2009.05.03.일][추가!!!]{***************************************
  //[저장소] 가 수정된 이후에야 [문자열] 을 수집 가능하다.
  //[수집 끝 위치]------------------------------------------------------------
  //이미 <pPASTEstr> 안에 [문자열] 을 추가한 상태이므로 이미 구한 <size> 값을
  //사용하여 처리한다.
  _history.strEndIndex = _caretindex + size;
  //[수집]--------------------------------------------------------------------
  //[추가] 수정이다.
  History_Add('+', 's');
  //}*************************************************************************

  //[후처리]
  //{
      //[문서량 수정]
      //{
          //추가한 문자의 길이만큼 [문서양] 이 는다.
          _filesize += size;

      //}

      //[행수 수정]
      //{
          //CRLF 가 삭제된 것이 있는 경우만 수정한다.
          if(crlf_count > 0) { _linecount += crlf_count; }

      //}

      //[묶음주석 정보 수집]
      //{
          //[2012.06.10.일][추가!!!]{---------------
          //반드시 [수정] 된 후에 [수집] 해야 한다.
          //}---------------------------------------

          //[2012.06.12.화][수정!!!]
          //부분정보 수집--------------------v
          cmtBlkChanged = _CommentBlock_Info(true);

      //}

      //[수정 반영]
      //{
          //[선택영역] 이 삭제된 경우는 <키> 를 처리하지 않고 여기서 종료하게
          //되므로 이곳에서 직접 수정된 내용을 반영해 주어야 한다.
          if((pReDraw == true) || (caretAlwaysView == true)) { _EditBuf_Text(); }

      //}

      //[수직스크롤설정]
      //{
          //수정된 행이 있는 경우는 문서행수가 바뀌었으므로 [수직스크롤] 을
          //새로 설정해 주어야 한다.(여기서 종료하므로 이곳에서 처리한다)
          if(crlf_count > 0) { _Scroll_Resize(); }

      //}

  //}

  //[입력지정자 위치 지정]
  //{
      //[2009.05.08.금][추가!!!]{-------------------------------------------------------
      //붙여넣기한 문자열 끝에 [입력지정자] 를 위치 시킨다.
      //행이 추가됬을수도 있으므로 반드시 _Scroll_Resize() 가 끝난 이위치에서 처리한다.
      //}-------------------------------------------------------------------------------

      //[입력지정자] 위치 수정(붙여넣기한 문자열 끝으로 이동).
      _caretindex += size;

      //[입력지정자] 이동.
      History_SetCaretPos(_caretindex, true);

  //}

  //[실시간 선언 정보판 관련]
  //{
      //[단어 구간 정보 추출]
      //{
          //[2012.05.24.목][추가!!!]{-------------------------------------------
          //실시간으로 [입력지정자] 가 위치한 [단어] 의 [시작/끝:위치] 를 관리.
          //}-------------------------------------------------------------------

          STR_Get_WordBound(_editbuf, _filesize, _caretindex,
                            &_wordStartIndex,
                            &_wordEndIndex);

      //}

      //[실시간 선언 정보판 감추기]
      //{
          //[2012.05.24.목][추가!!!]{----------------------------
          //[실시간 선언 정보판] 이 보이는 경우만 처리하고
          //처리후 반드시 [단어지정] 을 위하여 [입력지정자] 가
          //위치한행만 다시 그린다.
          //
          //더불어, <info_tree_Form->_AutoHide_WordBound()> 에서
          //기존 [단어 구간] 을 벗어난 경우는 자동으로 감춰진다.
          //}----------------------------------------------------

          if(info_tree_Form != NULL)
          {
            if((info_tree_Form->Visible == true) &&
               //[2012.06.01.금][추가!!!]
               //<_AutoHide_WordBound()> 함수 사용 허가상태만 처리.
               (info_tree_Form->_sw_AutoHide_WordBound == true))
            {
              //현재 [단어 구간 정보] 전달.
              info_tree_Form->_AutoHide_WordBound(_wordStartIndex, _wordEndIndex);

              //현재 [입력지정자] 가 위치한 행만 다시 그린다.
              _EditBuf_LineText(_row, false);

            }

          }

      //}
      
  //}

}

void __fastcall Teditor_edit_Form::_EDIT_SelectAll(void)
{
  //[2007.03.20.화][생성!!!]{-----------------------------------------------
  //[전체선택] 을 처리한다.
  //현재 보이는 영역이 그대로 보이도록 해야 하고 [줄이동] 은 하지 않는다.
  //단, [선택영역] 을 관리 하는 변수는 모두 정확한 값을 가지고 있어야 하고,
  //[입력지정자] 는 문서의 가장 끝에 위치해야 한다.
  //단, 이때 [입력지정자] 가 보이도록 다시 [줄이동] 하지 않아야 한다.
  //}-----------------------------------------------------------------------

  //[VAR]
  //{
      int  start_linestartindex;

      int  end_linestartindex,
           end_lineendindex;

      int  start_caretindexwidth,
           end_caretindexwidth;

      int  start_caret_x, start_caret_y;
      int  end_caret_x, end_caret_y;

      int  moonjacount, col;
      
  //}

  //[시작/끝 위치 얻기]
  //{
      //[시작위치]{----------------------------------------------------------------
      //가장 처음행의 시작위치를 구한다.
      _MOUSEDOWN_Get_LineStartIndex(0, &start_linestartindex);
      //[끝위치]-------------------------------------------------------------------
      //가장 마지막 행의 시작 위치를 구한다.
      //_linecount 값이 최소 1 을 갖고 행수(index 개념)과는 달리 1 부터 시작하므로
      // -1 을 해서 행번호로 수정하여 사용해야 한다.
      _MOUSEDOWN_Get_LineStartIndex(_linecount - 1, &end_linestartindex);
      //이 행의 끝 index 값 얻기.([선택영역] 끝 위치를 얻기 위한 것)
      STR_Get_ThisLineEndIndex(_editbuf, end_linestartindex, &end_lineendindex);
      //}--------------------------------------------------------------------------

  //}

  //[입력지정자 위치 얻기]
  //{
      //[설명]{--------------------------------------------------------------
      //[선택영역] 을 [문서] 의 [처음 ~ 끝] 까지 가상적으로 만드는 것이므로,
      //실제로 [입력지정자] 의 위치를 정확하게 계산하여 해당 정보 관리변수에
      //할당해 주어야 한다.
      //}--------------------------------------------------------------------

      //[caretindexwidth 구하기]
      //{
          //[시작위치]{-----------------------------------------------------------
          _CARETINDEX_CaretIndexWidth(start_linestartindex, start_linestartindex,
                                      &start_caretindexwidth, &moonjacount);
          //[끝위치]--------------------------------------------------------------
          _CARETINDEX_CaretIndexWidth(end_linestartindex, end_lineendindex,
                                      &end_caretindexwidth, &col);
          //}---------------------------------------------------------------------

      //}

      //[입력지정자 위치 구하기]
      //{
          //[시작위치]{----------------------------------
          //[문서] 상의 위치를 구한다.
          start_caret_x = start_caretindexwidth;
          start_caret_y = 0 * _line_height;
          //[끝위치]-------------------------------------
          //[문서] 상의 위치를 구한다.
          end_caret_x = end_caretindexwidth;
          end_caret_y = (_linecount - 1) * _line_height;
          //}--------------------------------------------

      //}

  //}

  //[선택영역 정보 설정]
  //{
      //[시작위치]{-------------------------------------
      _Select_CaretIndex(&_select_start, start_linestartindex); //_select_start.caret_index = start_linestartindex;
      _select_start.caret_x     = start_caret_x;
      _select_start.caret_y     = start_caret_y;
      //[끝위치]----------------------------------------
      _Select_CaretIndex(&_select_end, end_lineendindex); //_select_end.caret_index   = end_lineendindex;
      _select_end.caret_x       = end_caret_x;
      _select_end.caret_y       = end_caret_y;
      //}-----------------------------------------------

  //}

  //[입력지정자 위치 설정]
  //{
      //입력지정자는 문서의 가장 마지막에 위치시켜준다.(단, [줄이동] 은 해서는 안된다.)
      //_EDIT_CaretPos() 함수에서 [선택영역] 이 해제 되지 않도록 처리한다.
      _scroll_ing = true;
      //{
          //위에서 얻은 [열] 위치 값을 기록해 주어야 한다.
          //아래 _EDIT_CaretPos() 안에서는 _raw 만 계산이 된다.
          _col = col;

          //반드시 _caretindex 값을 설정해 주어야 한다.
          _caretindex = _select_end.caret_index;
          _caret_x    = _select_end.caret_x;
          _caret_y    = _select_end.caret_y;

          _EDIT_CaretPos(_caret_x, _caret_y);
      //}
      _scroll_ing = false;

  //}

  //[선택영역 반영]{-----------------------------
  //[선택영역] 을 반영하기 위하여 다시 그려준다.
  _EditBuf_Text();
  //}--------------------------------------------

  return;

}

void __fastcall Teditor_edit_Form::_Edit_SelectX(//선택 시작 위치.
                                                 int    pSelStartIndex,
                                                 //선택 끝 위치.
                                                 int    pSelEndIndex,
                                                 //true 인경우는 항상 [선택 영역] 을 항상 보이는 위치에 있게 한다.
                                                 bool   pSelView,
                                                 //[선택영역] 의 [시작행] 을 반환한다.
                                                 int   *rStartLineNumber,
                                                 //[2009.05.07.목][추가!!!]
                                                 //다시그리는 경우는 true.
                                                 bool   pReDraw)
{
  //[2009.02.17.화][생성!!!]{-------------------------------------------------
  //지정 영역을 선택해준다.
  //항상 지정된 영역이 보이도록 [입력지정자] 를 [선택된 영역] 앞에 위치시키고
  //해당 행이 항상 보이는 영역에 있도록 [줄이동] 도 해주어야 한다.
  //
  //[2009.02.18.수][수정!!!]--------------------------------------------------
  //STR_Get_LineNumber_withIndex() 함수로 [행번호] 를 먼저 구해서 처리한다.
  //
  //선택 시작/끝 [행번호] 는 [선택영역] 이 여러행에 걸쳐 있을수 있으므로
  //각각 계산한다.
  //}-------------------------------------------------------------------------

  //[VAR]
  //{
      int  start_LineStartIndex;

      int  end_LineStartIndex,
           end_LineEndIndex;

      int  start_CaretIndexWidth,
           end_CaretIndexWidth;

      int  start_CaretX, start_CaretY;
      int  end_CaretX, end_CaretY;

      int  moonjaCount, col;

      //[2009.02.18.수][추가!!!]
      //{
          //선택 시작 행번호.
          int  selStartLineNumber;

          //선택 끝 행번호.
          int  selEndLineNumber;

      //}

      //[2009.05.07.목][추가!!!]
      int   caretAlwaysView;

  //}

  //[행번호 얻기]
  //{
      //[행번호] 는 꼭 [선택영역] 이 같은행에 있지 않을수 있으므로 각각 별도 계산한다.

      selStartLineNumber = STR_Get_LineNumber_withIndex(_editbuf, pSelStartIndex);

      //[반환]
      //{
          //이 함수를 사용하는 곳에서 [선택영역] 을 항상 보여 주게 하기 위하여 [행번호]
          //가 필요하므로 이 선택영역 시작 [행번호] 를 반환해 준다.
          if(rStartLineNumber != NULL) { (*rStartLineNumber) = selStartLineNumber; }

      //}

      //행정보를 얻는 것은 시간을 많이 깍아 먹으므로 이전 행 수부터 다시 시작한다.
      selEndLineNumber   = selStartLineNumber +
                           //이전 행수에 다음 부터 CRLF 의 개수를 더하면 된다.
                           STR_Get_CRLF_Count_withStartEndIndex(_editbuf, pSelStartIndex, pSelEndIndex);

  //}

  //[시작/끝 위치 얻기]
  //{
      //[시작위치]
      //{
          //현재 행의 시작 위치를 얻는다.
          STR_Get_ThisLineStartIndex(_editbuf, pSelStartIndex, &start_LineStartIndex);

      //}

      //[끝위치]
      //{
          STR_Get_ThisLineStartIndex(_editbuf, pSelEndIndex, &end_LineStartIndex);

      //}

  //}

  //[입력지정자 위치 얻기]
  //{
      //[설명]{--------------------------------------------------------------
      //[선택영역] 을 [문서] 의 [지정범위] 에서  가상적으로 만드는 것이므로,
      //실제로 [입력지정자] 의 위치를 정확하게 계산하여 해당 정보 관리변수에
      //할당해 주어야 한다.
      //}--------------------------------------------------------------------

      //[caretindexwidth 구하기]
      //{
          //[시작위치]
          //{
              _CARETINDEX_CaretIndexWidth(start_LineStartIndex, pSelStartIndex,
                                          &start_CaretIndexWidth, &moonjaCount);

          //}

          //[끝위치]
          //{
              _CARETINDEX_CaretIndexWidth(end_LineStartIndex, pSelEndIndex,
                                          &end_CaretIndexWidth, &col);

          //}

      //}

      //[입력지정자 위치 구하기]
      //{
          //[시작위치]
          //{
              //[문서] 상의 위치를 구한다.
              start_CaretX = start_CaretIndexWidth;
              start_CaretY = selStartLineNumber * _line_height;

          //}

          //[끝위치]
          //{
              //[문서] 상의 위치를 구한다.
              end_CaretX = end_CaretIndexWidth;
              end_CaretY = selEndLineNumber * _line_height;

          //}

      //}

  //}

  //[선택영역 정보 설정]
  //{
      //[시작위치]
      //{
          _Select_CaretIndex(&_select_start, pSelStartIndex); //_select_start.caret_index = pSelStartIndex;
          _select_start.caret_x     = start_CaretX;
          _select_start.caret_y     = start_CaretY;

      //}

      //[끝위치]
      //{
          _Select_CaretIndex(&_select_end, pSelEndIndex); //_select_end.caret_index   = pSelEndIndex;
          _select_end.caret_x       = end_CaretX;
          _select_end.caret_y       = end_CaretY;

      //}

  //}

  //[입력지정자 위치 설정]
  //{
      //[입력지정자] 는 지정 위치에 있어야 한다(실제 선택영역 시작 위치).
      //_EDIT_CaretPos() 함수에서 [선택영역] 이 해제 되지 않도록 처리한다.
      _scroll_ing = true;
      //{
          //위에서 얻은 [열] 위치 값을 기록해 주어야 한다.
          //아래 _EDIT_CaretPos() 안에서는 _raw 만 계산이 된다.
          _col = col;

          //반드시 _caretindex 값을 설정해 주어야 한다.
          _caretindex = _select_start.caret_index;
          _caret_x    = _select_start.caret_x;
          _caret_y    = _select_start.caret_y;

          _EDIT_CaretPos(_caret_x, _caret_y);

      //}

      _scroll_ing = false;

  //}

  //[선택 영역 보이기]
  //{
      if(pSelView == true)
      {
        //[참고!!!]{----------------------------------------------------------
        //일단 [줄이동] 시에는 [다시출력] 하지 않게 만든다.
        //여러 가지가 있으니 사용하지 않는 _edit_paste_ing 사용하여 처리한다.
        //}-------------------------------------------------------------------

        _edit_paste_ing = true;
        //{
            //[중요!!!]{---------------------------------------------------------------------
            //_CARET_ViewAlways() 함수도 같이 사용한다.
            //_Line_View() 함수는 [수평] 으로 [줄이동] 은 하지 않으므로
            //[선택 영역] 이 [수평] 으로 영역을 벗어나 있는 경우는 확실하게 보여주지 못한다.
            //따라서, 먼저 _CARET_ViewAlways() 함수로 확실하게 보이는 영역에 위치 시키고
            //_Line_View() 함수로 여유있게 보이는 위치로 다시 수정해 놓는다.
            //이미 위에서 _edit_paste_ing = true; 로 다시 문서를 출력하지 못하게 만들어
            //놓았으므로 중복출력으로인한 [까박거림] 현상이 없이 깔끔하게 처리된다.
            //}------------------------------------------------------------------------------

            //먼저 확실하게 보이게 만든다(수평/수직 둘다 처리).

            //[2009.05.08.금][수정!!!]
            //보다 기능이 다양한 강력한 함수로 교체한다.
            caretAlwaysView = _Caret_ViewAlways_Middle(false, //위쪽은 기본 보이는 영역으로.
                                                       true); //아래쪽의 경우는 무조건 중간에 위치시키기.

            //더 확실하고 여유있게 위치를 이동 시킨다(수직적인 처리).
            ide_editor_Form->_Line_View(selStartLineNumber);

        //}
        _edit_paste_ing = false;

      }

  //}

  //[선택영역 반영]
  //{
      //[선택영역] 을 반영하기 위하여 유일하게 여기서 한번 다시 그려준다.
      if((pReDraw == true) || (caretAlwaysView == true)) { _EditBuf_Text(); }

  //}

  return;

}

void __fastcall Teditor_edit_Form::_Edit_Select_Off(void)
{
  //[2022.05.30.월][생성]{-----------------------------------------------------
  //현재 [편집기] 의 선택영역을 해제시킨다.
  //
  //[참고]*********************************************************************
  //[API 자동 추가 기능] 을 구현하던중 오류가 없이 종료되는 경우인데도, 이전에
  //추가되지 않은 API 를 사용한 부분을 [선택영역] 으로 지정한 것이 그대로 남아
  //보기 좋지 않으므로 이를 해제 하고 종료하기 위한것.
  //}--------------------------------------------------------------------------

  //[선택영역 해제]
  //{
      _Select_CaretIndex(&_select_start, -1);

      _Select_CaretIndex(&_select_end, -1);

  //}

  //[다시 그리기]
  //{
      //[선택영역:해제] 를 반영하기 위하여 다시 그린다.
      _EditBuf_Text();

  //}

}

void __fastcall Teditor_edit_Form::_Mouse_WordSelect(void)
{
  //[2009.05.08].금][생성!!!]{-------------------------------------------------------------
  //원래 [다중눌림] 의 경우 현재 [입력지정자] 를 포함하는 단어를 지정하게 되나
  //왠일인지 BCB 에서 [다중눌림] 의 경우 제대로 동작이 안되는 경우가 발생하여
  //부득이 하게 [마우스 가운데눌림] 의 경우 이 함수로 호출하여 처리하는 것으로 처리하였다.
  //}--------------------------------------------------------------------------------------

  //[VAR]
  //{
      int   wordStartIndex;
      int   wordEndIndex;

  //}

  //[단어 선택]
  //{
      //[단어] 는 연산자 기호등을 제외한 순순한 문자열의 경우만 해당된다.

      //현재 [입력지정자] 를 포함하고 있는 단어의 [시작/끝 위치] 를 얻는다.
      STR_Get_WordBound(_editbuf, _filesize, _caretindex, &wordStartIndex, &wordEndIndex);

      //[단어] 를 [선택영역] 으로 지정해 준다.
      History_SelectX(wordStartIndex, wordEndIndex, true, NULL, true,
                      //이 경우는 항상 이미 보이는 영역에 있으므로 그대로 둔다.
                      false, false);

  //}

  return;

}
/*
void __fastcall Teditor_edit_Form::_Select_CaretIndex(//<_select_start/_select_end> 만 사용한다.
                                                      struct CARETINFO  *pSelectX_CaretInfo,
                                                      //[입력지정자] 위치.
                                                      int                pCaretIndex)
{
  //[2011.06.23.목][생성!!!]{---------------------------------------------------------------------
  //<_select_start.caret_index> 과 <_select_end.caret_index> 에 값을 설정할때는
  //반드시 이 함수를 사용한다.
  //
  //이는 [검증식 보기판] 이 [선택영역] 의 [존재] 에 따라 [보이기/감추기] 가 결정되기 때문이다.
  //
  //워낙 많은 곳에서 [선택영역] 을 설정/해제 하기 때문에 일일히 감지하기 어렵지만
  //[선택영역] 은 결국 <_select_start.caret_index> 과 <_select_end.caret_index> 에 값이 
  //<-1> 인 경우는 [선택영역이 존재하지 않음] 이 되고 값이 존재하는 경우는 [선택영역이 존재] 하는
  //것으로 간단하게 구별할수 있다.
  //
  //추가로, 여기서 [검증식 보기판] 의 [보기/감추기] 관련 처리를 같이 수행한다.
  //
  //[주의!!!]-------------------------------------------------------------------------------------
  //반드시 <_select_start> 나 <_select_end> 만 사용해야 한다.
  //
  //[2011.06.25.토][추가!!!]----------------------------------------------------------------------
  //[선택영역] 의 변화가 있을 경우는 무조건 [기본상태(+)] 로 전환시킨다.
  //이는 이미 <-> 상태로 값이 보이고 있는 경우 [선택영역] 이 수정될때 이 상태가 계속되어
  //값이 일치하지 않기 때문이다.
  //
  //[2011.07.19.화][수정!!!]----------------------------------------------------------------------
  //[선택영역] 이 새로 만들어 지거나, 해제되는 경우는 항상 [검증식 보기판] 을 [기본보기] 상태로
  //만들어 준다([고정보기] 해제).
  //}---------------------------------------------------------------------------------------------

  //[끝 위치가 변경중인가?]
  //{
      //[2011.06.25.토][추가!!!]{------------------------------------
      //[선택영역:끝위치] 가 변경중인 경우는 항상 [검증식 보기판] 은
      //<+> 설정을 적용해야 한다.
      //}------------------------------------------------------------

      //[검증식 보기판] 이 보이고 있는 경우만 처리한다.
      //[2011.06.30.목][수정!!!]
      //[<*.c> 문서] 의 경우만 처리한다.
      if((_dbgView_Enable == true) && (_dbgView_Visible == true) && (_fileKind == d_Editor_FileKind_c))
      {
        //이전값과 다른 값인 경우는 [선택영역] 의 변화가 있는 경우다.

        //[2011.06.30.목][주의!!!]{---------------------------------------
        //현재 <pCaretIndex> 가 [양수/음수] 에 관계없이 처리해야 한다.
        //이는 기존 상태를 닫고 <+> 상태로 바꾸는데 의미가 있기 때문이다.
        //}---------------------------------------------------------------
        if(pSelectX_CaretInfo->caret_index != pCaretIndex)
        {
          if(pCaretIndex >= 0)
          {
            //현재 [기본상태(+)] 가 아닌 경우만 처리한다.
            if((_dbgView_State != '+') ||
                //[2011.07.19.화][추가!!!]
                //[고정보기] 인 경우는 기본상태로 돌려준다.
               (_dbgView_FixView == true))
            {
              //[기본상태(+)] 로 전환시킨다.
              _dbgView_State = '+';

              //[2011.07.19.화][추가!!!]{-----------------------------------------
              //새로 문자열이 설정되는 경우는 항상 [기본상태] 로 시작하게 만든다.
              //이는 [추가버튼] 을 사용하기 위한 것이다.
              _dbgView_FixView = false;
              //}-----------------------------------------------------------------

              _DbgView_Shape();

            }

          }
          else
          {
            _dbgView_State = '+';
            _dbgView_Visible = false;

          }

        }

      }

  //}

  //[기본처리]
  //{
      pSelectX_CaretInfo->caret_index = pCaretIndex;

  //}

  //[검증식 보기판 관련 처리]
  //{
      //[!]{-----------------------------------------------------------------
      //여기서 [선택영역] 이 [생성] 되는 것인지 [해제] 되는것인지만 구분하여
      //해당 처리를 수행한다.
      //}--------------------------------------------------------------------

      //[<*.c> 문서인가?]
      //{
          //[2011.06.30.목][추가!!!]{----------------------
          //<*.c> 문서만 [검증식 보기판] 을 처리해야 한다.
          //}----------------------------------------------

          if((_dbgView_Enable == true) && (_fileKind != d_Editor_FileKind_c)) return;

      //}

      if((_select_start.caret_index >= 0) && (_select_end.caret_index >= 0))
      {
        //[!]{---------------------------------------------------------
        //둘다 <-1> 이 아닌 경우는 [생성] 중이거나 생성돼 있는 경우다.
        //[검증식 보기판] 을 [보기 형식] 에 맞게 보여준다.
        //이미 보이고 있는 경우는 처리할 필요가 없다.
        //}------------------------------------------------------------

        if(_dbgView_Visible == false)
        {
          _DbgView_Shape();

          _dbgView_Visible = true;

        }

      }
      else
      {
        //둘중 한개라도 <-1> 로 설정되는 경우는 [해제] 되는 경우다.
        _dbgView_Visible = false;

        //[2011.06.25.토][추가!!!]
        //기본상태로 돌려 놓는다.
        _dbgView_State = '+';

        //[2011.07.19.화][추가!!!]{-----------------------------------------
        //새로 문자열이 설정되는 경우는 항상 [기본상태] 로 시작하게 만든다.
        //이는 [추가버튼] 을 사용하기 위한 것이다.
        _dbgView_FixView = false;
        //}-----------------------------------------------------------------

      }

  //}

}
*/

void __fastcall Teditor_edit_Form::_Select_CaretIndex(//<_select_start/_select_end> 만 사용한다.
                                                      struct CARETINFO  *pSelectX_CaretInfo,
                                                      //[입력지정자] 위치.
                                                      int                pCaretIndex)
{
  //[2011.06.23.목][생성!!!]{---------------------------------------------------------------------
  //<_select_start.caret_index> 과 <_select_end.caret_index> 에 값을 설정할때는
  //반드시 이 함수를 사용한다.
  //
  //이는 [검증식 보기판] 이 [선택영역] 의 [존재] 에 따라 [보이기/감추기] 가 결정되기 때문이다.
  //
  //워낙 많은 곳에서 [선택영역] 을 설정/해제 하기 때문에 일일히 감지하기 어렵지만
  //[선택영역] 은 결국 <_select_start.caret_index> 과 <_select_end.caret_index> 에 값이 
  //<-1> 인 경우는 [선택영역이 존재하지 않음] 이 되고 값이 존재하는 경우는 [선택영역이 존재] 하는
  //것으로 간단하게 구별할수 있다.
  //
  //추가로, 여기서 [검증식 보기판] 의 [보기/감추기] 관련 처리를 같이 수행한다.
  //
  //[주의!!!]-------------------------------------------------------------------------------------
  //반드시 <_select_start> 나 <_select_end> 만 사용해야 한다.
  //
  //[2011.06.25.토][추가!!!]----------------------------------------------------------------------
  //[선택영역] 의 변화가 있을 경우는 무조건 [기본상태(+)] 로 전환시킨다.
  //이는 이미 <-> 상태로 값이 보이고 있는 경우 [선택영역] 이 수정될때 이 상태가 계속되어
  //값이 일치하지 않기 때문이다.
  //
  //[2011.07.19.화][수정!!!]----------------------------------------------------------------------
  //[선택영역] 이 새로 만들어 지거나, 해제되는 경우는 항상 [검증식 보기판] 을 [기본보기] 상태로
  //만들어 준다([고정보기] 해제).
  //}---------------------------------------------------------------------------------------------

  //[끝 위치가 변경중인가?]
  //{
      //[2011.06.25.토][추가!!!]{------------------------------------
      //[선택영역:끝위치] 가 변경중인 경우는 항상 [검증식 보기판] 은
      //<+> 설정을 적용해야 한다.
      //}------------------------------------------------------------

      //[검증식 보기판] 이 보이고 있는 경우만 처리한다.
      //[2011.06.30.목][수정!!!]
      //[<*.c> 문서] 의 경우만 처리한다.
      if((_dbgView_Enable == true) && (_dbgView_Visible == true) && (_fileKind == d_Editor_FileKind_c))
      {
        //이전값과 다른 값인 경우는 [선택영역] 의 변화가 있는 경우다.

        //[2011.06.30.목][주의!!!]{---------------------------------------
        //현재 <pCaretIndex> 가 [양수/음수] 에 관계없이 처리해야 한다.
        //이는 기존 상태를 닫고 <+> 상태로 바꾸는데 의미가 있기 때문이다.
        //}---------------------------------------------------------------
        if(pSelectX_CaretInfo->caret_index != pCaretIndex)
        {
          if(pCaretIndex >= 0)
          {
            //현재 [기본상태(+)] 가 아닌 경우만 처리한다.
            if(_dbgView_State != '+')
            {
              //[기본상태(+)] 로 전환시킨다.
              _dbgView_State = '+';

              _DbgView_Shape();

            }

          }
          else
          {
            _dbgView_State = '+';
            _dbgView_Visible = false;

          }

        }

      }

  //}

  //[기본처리]
  //{
      pSelectX_CaretInfo->caret_index = pCaretIndex;

  //}

  //[검증식 보기판 관련 처리]
  //{
      //[!]{-----------------------------------------------------------------
      //여기서 [선택영역] 이 [생성] 되는 것인지 [해제] 되는것인지만 구분하여
      //해당 처리를 수행한다.
      //}--------------------------------------------------------------------

      //[<*.c> 문서인가?]
      //{
          //[2011.06.30.목][추가!!!]{----------------------
          //<*.c> 문서만 [검증식 보기판] 을 처리해야 한다.
          //}----------------------------------------------

          if((_dbgView_Enable == true) && (_fileKind != d_Editor_FileKind_c)) return;

      //}

      if((_select_start.caret_index >= 0) && (_select_end.caret_index >= 0))
      {
        //[!]{---------------------------------------------------------
        //둘다 <-1> 이 아닌 경우는 [생성] 중이거나 생성돼 있는 경우다.
        //[검증식 보기판] 을 [보기 형식] 에 맞게 보여준다.
        //이미 보이고 있는 경우는 처리할 필요가 없다.
        //}------------------------------------------------------------

        if(_dbgView_Visible == false)
        {
          _DbgView_Shape();

          _dbgView_Visible = true;

        }

      }
      else
      {
        //둘중 한개라도 <-1> 로 설정되는 경우는 [해제] 되는 경우다.
        _dbgView_Visible = false;

        //[2011.06.25.토][추가!!!]
        //기본상태로 돌려 놓는다.
        _dbgView_State = '+';

      }

  //}

}

//[동작함수]--------------------------------------------------------------------

/*
void __fastcall Teditor_edit_Form::_EVENT_PopupMenu(void)
{
  //[2007.03.06.화][생성!!!]{-----------------------------------------
  //[간편기능항목] 에서 항목이 선택된 경우 이 함수를 호출하게 되는데,
  //선택된 항목의 index 를 구하여 해당 항목의 처리를 수행한다.
  //}-----------------------------------------------------------------

  //[촛점설정]
  //{
      //[2007.03.31.토][추가!!!]
      //[빠른항목] 의 경우는 모든 동작이 [편집기] 에 국한 되므로
      //동작 전에 항상 [편집기] 에 촛점을 맞추어 준다.
      this->SetFocus();

  //}

  switch(_popup_menu_->_subitem.select_index)
  {
    case 0 : //복사.
    {
      _CLIPBOARD_Copy();

    } break;

    case 1 : //잘라내기.
    {
      //[읽기전용인가?][2009.03.31.화][추가!!!]{---
      //[읽기전용] 인 경우는 수정하지 않는다.
      if(_readOnly == true) break;
      //[2009.04.25.토][추가!!!]
      if(_readOnlyAll == true) break;
      //}------------------------------------------

      //[문서수정]{-----------------
      //[2007.03.목][추가!!!]
      //문서가 수정됬음을 기록한다.
      _EDIT_Changed(false, true);
      //}---------------------------

      //[2009.06.02.화][수정!!!]{----------------------------------
      //[묶음주석] 처리를 위하여 _EDIT_Changed() 와 순서를 바꾼다.
      //}----------------------------------------------------------

      _CLIPBOARD_Cut(true);

    } break;

    case 2 : //붙이기.
    {
      //[읽기전용인가?][2009.03.31.화][추가!!!]{---
      //[읽기전용] 인 경우는 수정하지 않는다.
      if(_readOnly == true) break;
      //[2009.04.25.토][추가!!!]
      if(_readOnlyAll == true) break;
      //}------------------------------------------

      //[문서수정]{-----------------
      //[2007.03.목][추가!!!]
      //문서가 수정됬음을 기록한다.
      _EDIT_Changed(false, true);
      //}---------------------------

      //[2009.06.02.화][수정!!!]{----------------------------------
      //[묶음주석] 처리를 위하여 _EDIT_Changed() 와 순서를 바꾼다.
      //}----------------------------------------------------------

      _CLIPBOARD_Paste(true);

    } break;

    case 3 : //삭제.
    {
      //[읽기전용인가?][2009.03.31.화][추가!!!]{---
      //[읽기전용] 인 경우는 수정하지 않는다.
      if(_readOnly == true) break;
      //[2009.04.25.토][추가!!!]
      if(_readOnlyAll == true) break;
      //}------------------------------------------

      //[문서수정]{-----------------
      //[2007.03.목][추가!!!]
      //문서가 수정됬음을 기록한다.
      _EDIT_Changed(false, true);
      //}---------------------------

      //[2009.06.02.화][수정!!!]{----------------------------------
      //[묶음주석] 처리를 위하여 _EDIT_Changed() 와 순서를 바꾼다.
      //}----------------------------------------------------------

      _EDIT_SelectDelete();  

    } break;

    case 4 : //모두선택.
    {
      _EDIT_SelectAll();

    } break;

  }

  return;

}
*/

void __fastcall Teditor_edit_Form::_EVENT_PopupMenu(void)
{
  //[2011.07.24.일][생성!!!]{----------------------------------------------------
  //위에서 [주석문] 으로 처리된 이전 방식과 달리, [문자열] 방식으로 새로 만든다.
  //[항목] 이 가변적인 경우라도 [항목이름] 으로 골라서 처리 가능하므로 처리부가
  //섞여 있어도 상관없으며 이게 더 관리하는데 효과적이다.
  //}----------------------------------------------------------------------------

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

  //}

  //[촛점설정]
  //{
      //[!]{-----------------------------------------------------
      //[빠른항목] 의 경우는 모든 동작이 [편집기] 에 국한 되므로
      //동작 전에 항상 [편집기] 에 촛점을 맞추어 준다.
      //}--------------------------------------------------------

      this->SetFocus();

  //}

  //[항목 문자열 얻기]
  //{
      //[!]{-------------------------------------------------------------------------
      //다음에서 [항목 문자열] 로 구분 처리를 하므로 선택된 [항목 문자열] 을 얻는다.
      //}----------------------------------------------------------------------------
      
      STR_Assign(menuStr, _popup_menu_->_subitem.str[_popup_menu_->_subitem.select_index].c_str());

  //}

  if     (STR_Match(menuStr, " 복사 "))
  {
    _CLIPBOARD_Copy();

  }
  else if(STR_Match(menuStr, " 잘라내기 "))
  {
    //[읽기전용인가?][2009.03.31.화][추가!!!]{---
    //[읽기전용] 인 경우는 수정하지 않는다.
    if(_readOnly == true) return;
    //[2009.04.25.토][추가!!!]
    if(_readOnlyAll == true) return;
    //}------------------------------------------

    //[문서수정]{-----------------
    //[2007.03.목][추가!!!]
    //문서가 수정됬음을 기록한다.
    _EDIT_Changed(false, true);
    //}---------------------------

    //[2009.06.02.화][수정!!!]{----------------------------------
    //[묶음주석] 처리를 위하여 _EDIT_Changed() 와 순서를 바꾼다.
    //}----------------------------------------------------------

    _CLIPBOARD_Cut();

  }
  else if(STR_Match(menuStr, " 붙이기 "))
  {
    //[읽기전용인가?][2009.03.31.화][추가!!!]{---
    //[읽기전용] 인 경우는 수정하지 않는다.
    if(_readOnly == true) return;
    //[2009.04.25.토][추가!!!]
    if(_readOnlyAll == true) return;
    //}------------------------------------------

    //[문서수정]{-----------------
    //[2007.03.목][추가!!!]
    //문서가 수정됬음을 기록한다.
    _EDIT_Changed(false, true);
    //}---------------------------

    //[2009.06.02.화][수정!!!]{----------------------------------
    //[묶음주석] 처리를 위하여 _EDIT_Changed() 와 순서를 바꾼다.
    //}----------------------------------------------------------

    _CLIPBOARD_Paste();

  }
  else if(STR_Match(menuStr, " 삭제 "))
  {
    //[읽기전용인가?][2009.03.31.화][추가!!!]{---
    //[읽기전용] 인 경우는 수정하지 않는다.
    if(_readOnly == true) return;
    //[2009.04.25.토][추가!!!]
    if(_readOnlyAll == true) return;
    //}------------------------------------------

    //[문서수정]{-----------------
    //[2007.03.목][추가!!!]
    //문서가 수정됬음을 기록한다.
    _EDIT_Changed(false, true);
    //}---------------------------

    //[2009.06.02.화][수정!!!]{----------------------------------
    //[묶음주석] 처리를 위하여 _EDIT_Changed() 와 순서를 바꾼다.
    //}----------------------------------------------------------

    _EDIT_SelectDelete();

  }
  else if(STR_Match(menuStr, " 모두선택 "))
  {
    _EDIT_SelectAll();

  }
  else if(STR_Match(menuStr, " 검증식 보기창에 추가 "))
  {
    //[2011.07.24.일][추가!!!]{------------------------------
    //선택된 [검증식 문자열] 을 [검증식 보기창] 에 등록한다.
    //}------------------------------------------------------

    //전용 처리 함수를 호출하여 처리한다.
    _Event_dbgView_bmp_AddBtn();

  }
  else if(STR_Match(menuStr, " 검증식 작성 "))
  {
    //[2012.09.19.수][추가!!!]{-----------
    //검증식 문자열을 직접 작성하여 추가.
    //}-----------------------------------

    //전용 함수로 처리.
    _DbgView_ExpStr_Edit();

  }

}

void __fastcall Teditor_edit_Form::_PopupMemu_Set(bool  pTeditFdebug)
{
  //[2011.07.24.일][생성!!!]{--------------------------------------------
  //[편집/검증] 시를 구분하여 각각의 [항목] 을 보여주는 것으로 수정한다.
  //}--------------------------------------------------------------------

  //[VAR]
  //{
      int  i;

  //}

  if(pTeditFdebug == true)
  {
    //[!]{------------------------
    //[편집기] 항목으로 설정한다.
    //}---------------------------

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

        _popup_menu_->_subitem.str[i++] = " 복사 ";
        _popup_menu_->_subitem.str[i++] = " 잘라내기 ";
        _popup_menu_->_subitem.str[i++] = " 붙이기 ";
        _popup_menu_->_subitem.str[i++] = " 삭제 ";
        _popup_menu_->_subitem.str[i++] = " 모두선택 ";

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

    //}

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

  }
  else
  {
    //[!]{----------------------
    //[검증] 항목으로 설정한다.
    //}-------------------------

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

        _popup_menu_->_subitem.str[i++] = " 복사 ";
        _popup_menu_->_subitem.str[i++] = " 모두선택 ";
        _popup_menu_->_subitem.str[i++] = "------------------";
        _popup_menu_->_subitem.str[i++] = " 검증식 보기창에 추가 ";

        //[2012.09.19.수][추가!!!]
        _popup_menu_->_subitem.str[i++] = " 검증식 작성 ";

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

    //}

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

  }

  return;

}

//------------------------------------------------------------------------------
//[클립보드관련]----------------------------------------------------------------
//------------------------------------------------------------------------------

bool __fastcall Teditor_edit_Form::_CLIPBOARD_IsText(void)
{
  //[2007.03.06.화][생성!!!]{-------------------------
  //현재 [클립보드] 안의 내용이 [문서] 인지 확인한다.
  //}-------------------------------------------------

  if(Clipboard()->HasFormat(CF_TEXT) == true) { return(true); }

  return(false);

}

void __fastcall Teditor_edit_Form::_CLIPBOARD_Copy(void)     
{
  //[2007.03.07.수][생성!!!]{---------------------------------------------
  //이미 _select_start, _select_end 구조체 정보에 들어 있는 것을 참고하여
  //현재 [선택영역] 의 문자열을 [클립보드] 에 넣어준다.
  //메모리를 절약하기 위하여 동적 생성으로 처리한다.
  //}---------------------------------------------------------------------

  //[VAR]
  //{
      struct CARETINFO   select_start;
      struct CARETINFO   select_end;

      //선택된 문자열을 저장하기 위한 저장소.
      char              *select_text = NULL;
      //'\0' 까지 포함된 크기를 가져야 한다.
      int                size;

  //}

  //[유효확인]
  //{
      //[2007.10.01.월][추가!!!]
      //이 편집기가 동작 가능한 상태일 경우만 처리한다.
      if(ide_editor_Form->Enabled != true) return;

  //}

  //[선택영역 정보 구하기]
  //{
      //[선택영역] 이 없는 경우는 바로 종료한다.
      if(_SELECT_Get_StartEndIndex(&select_start, &select_end) != true) return;

      //문자열 길이 얻기. '\0' 을 포함한 크기여야 한다.----------v
      size = select_end.caret_index - select_start.caret_index + 1;

  //}

  //[저장소 처리]
  //{
      //[저장소] 를 동적 생성한다.
      //select_text = new char [size];
      //[동적생성단위적용][2021.01.24.일][수정]
      select_text = new char [UnitX(1024, size)];

      //[선택영역] 문자열을 추출하여 저장한다.(자동으로 뒤에 '\0' 이 붙어서 반환된다.)
      STR_SubString(_editbuf,
                    select_start.caret_index, select_end.caret_index - select_start.caret_index,
                    select_text);

  //}

  //[클립보드에 할당]
  //{
      Clipboard()->AsText = (AnsiString)select_text;

  //}

  //[후처리]
  //{
      //동적 생성한 [저장소] 를 삭제한다.
      if(select_text != NULL) { delete [] select_text; select_text = NULL; }

  //}

}

void __fastcall Teditor_edit_Form::_CLIPBOARD_Cut(void)
{
  //[2007.03.07.수][생성!!!]{--------------------------------
  //[복사] 수행후 [선택영역] 을 삭제하면 된다.

  //[2007.03.22.목][수정!!!]---------------------------------
  //[선택영역] 이 존재하지 않는 경우는 처리하지 않아야 한다.
  //
  //[2012.06.11.월][수정!!!]---------------------------------
  //}--------------------------------------------------------

  //[VAR]
  //{
      struct CARETINFO   select_start;
      struct CARETINFO   select_end;
  //}

  //[유효확인]
  //{
      //[2007.10.01.월][추가!!!]
      //이 편집기가 동작 가능한 상태일 경우만 처리한다.
      if(ide_editor_Form->Enabled != true) return;

  //}

  //[선택영역 존재 확인]
  //{
      //[선택영역] 이 없는 경우는 바로 종료한다.
      if(_SELECT_Get_StartEndIndex(&select_start, &select_end) != true) return;

  //}

  //일단 [복사] 를 수행한 다음에 [선택영역] 을 삭제하면 된다.
  _CLIPBOARD_Copy();


  //[수정이력][2009.05.03.일][추가!!!]{*****************
  //[수정이력] 은 _KEY_Delete() 함수에서 자동 처리된다.
  //}***************************************************


  //[삭제] 는 <Del-Key> 를 누른 것으로 간단하게 처리할수 있다.
  _KEY_Delete(true);

}

void __fastcall Teditor_edit_Form::_CLIPBOARD_Paste(void)
{
  //[2007.03.07.수][생성!!!]{---------
  //내용이 있는 경우만 처리해야 한다.
  //
  //[2012.06.11.월][수정!!!]----------
  //[2019.03.08.금][중요수정]*********
  //[CRLF:완성] 처리부 추가.
  //}---------------------------------

  //[VAR]
  //{
      //[2019.03.08.금][추가]
      char  *strBuf  = NULL;

      int    strSize = 0;

  //}

  //[유효확인]
  //{
      //[2007.10.01.월][추가!!!]{-----------------------
      //이 편집기가 동작 가능한 상태일 경우만 처리한다.
      //}-----------------------------------------------

      if(ide_editor_Form->Enabled != true) return;

  //}

  //[내용이 문서인가?]
  //{
      //[문서] 가 아니라면 처리하지 않는다.
      if(_CLIPBOARD_IsText() != true) return;

  //}

  //[내용이 있는가?]
  //{
      //처리할 내용이 없다면 처리하지 않는다.
      if(((AnsiString)(Clipboard()->AsText)).Length() == 0) return;

  //}
      
  //[CRLF 완성/붙여넣기]
  //{
      //[2019.03.08.금][추가]{------------------------------------------------
      //[클립보드] 의 문자열에 [CR/LF] 등 [CRLF] 가 아닌 경우 [CRLF] 로 교체.
      //이는 [Linux:Wine] 지원을 위하여 절대적으로 필요.
      //전용 처리 함수로 처리.
      //}---------------------------------------------------------------------

      //[붙여넣기] 할 문자열의 크기 얻기.
      strSize = ((AnsiString)(Clipboard()->AsText)).Length();

      //[저장소:생성]
      //{
          //[!]{------------------------------------------------------
          //[붙여넣기] 할 문자열을 저장할 새 저장소 생성.
          //이는 <Str_CRLF_Complete()> 함수는
          //
          //1) CRLF 완성까지 수용할수 있는 새저장소 생성.
          //2) [원본] => [새저장소] 로 복사하면서 CRLF 완성.
          //3) [원본] 삭제.
          //4) [새저장소] 주소 반환(바꿔치기).
          //
          //방식을 처리 하기 때문에 반드시 [포인터] 를 사용해야 한다.
          //}---------------------------------------------------------

          //'\0' 까지 저장-------------v
          //strBuf = new char [strSize + 1];
          //[동적생성단위적용][2021.01.24.일][수정]
          strBuf = new char [UnitX(1024, strSize + 1)];

      //}

      //[붙여넣기] 할 문자열 저장.
	  STR_Assign(strBuf, ((AnsiString)(Clipboard()->AsText)).c_str());

      //CRLF 완성 처리(strBuf(주소), strSize(크기) 는 내부적으로 수정된것).
      Str_CRLF_Complete(&strBuf, &strSize);

      //[붙여넣기]
      //{
          //[클립보드] 안의 [문서] 내용을 현재 [입력지정자] 위치에 끼워넣는다.
          _EDIT_Paste(strBuf, true);

      //}

      //반드시 여기서 생성된 저장소 삭제.
      if(strBuf != NULL) { delete [] strBuf; strBuf = NULL; }

  //}

}

/*
void __fastcall Teditor_edit_Form::_CLIPBOARD_Paste(void)
{
  //[2007.03.07.수][생성!!!]{---------
  //내용이 있는 경우만 처리해야 한다.
  //
  //[2012.06.11.월][수정!!!]----------
  //}---------------------------------

  //[유효확인]
  //{
      //[2007.10.01.월][추가!!!]{-----------------------
      //이 편집기가 동작 가능한 상태일 경우만 처리한다.
      //}-----------------------------------------------

      if(ide_editor_Form->Enabled != true) return;

  //}

  //[내용이 문서인가?]{------------------------------------------------
  //[문서] 가 아니라면 처리하지 않는다.
  if(_CLIPBOARD_IsText() != true) return;
  //[내용이 있는가?]---------------------------------------------------
  //처리할 내용이 없다면 처리하지 않는다.
  if(((AnsiString)(Clipboard()->AsText)).Length() == 0) return;

  //[붙여넣기]---------------------------------------------------------
  //[클립보드] 안의 [문서] 내용을 현재 [입력지정자] 위치에 끼워넣는다.
  _EDIT_Paste(Clipboard()->AsText.c_str(), true);
  //}------------------------------------------------------------------

}
*/

//------------------------------------------------------------------------------
//[묶음수평이동 기능관련]-------------------------------------------------------
//------------------------------------------------------------------------------

bool __fastcall Teditor_edit_Form::_LineBlock_MoveRL_Right(//추가할 공백수.
                                                           int  pSpaceCount)
{
  //[2012.01.28.토][생성!!!]{----------------------------------------------------
  //[지정영역] 의 문자열의 각 행 시작 부분에 지정수의 [공백] 을 추가해 준다.
  //결과적으로 지정범위 안의 모든 행의 문자열이 오른쪽으로 수평 이동하게 되는것.
  //
  //단, 완벽한 [시작행의 시작위치], [끝행의 시작위치] 는 여기서 구해야 한다.
  //
  //[주의!!!]--------------------------------------------------------------------
  //선택 영역의 끝위치 정보는 [마지막행 시작위치] 를 미리 구해 놓아도
  //시작행부터 처리하면서 [공백] 을 추가하므로 계속 변하게 된다.
  //따라서, [마지막행 시작위치] 는 추가되는 [공백수] 만큼 계속 증가해야 한다.
  //
  //[마지막행 시작위치] += pSpaceCount;
  //
  //[2012.02.02.목][중요수정!!!]-------------------------------------------------
  //아무 문자가 없는 [NULL행] 인 경우는 수평이동 하지 않고 그대로 둔다.
  //이는 [오른쪽/왼쪽:수평이동] 시 조건을 동일하게 하기 위한것.
  //
  //[2012.02.04.토][중요수정!!!]-------------------------------------------------
  //[NULL행] 인 경우 변화가 없으므로, [입력지정자] 와 [선택영역] 도 역시 이
  //규칙에 따라 해당 행이 [NULL행] 에 해당하는 경우는 [정보] 를 수정하지 않는다.
  //
  //[2012.02.07.화][중요추가!!!]-------------------------------------------------
  //[수정이력] 등록 처리 추가.
  //}----------------------------------------------------------------------------

  //[VAR]
  //{
      //[선택영역] 정보를 순서대로 얻기 위한것.
      struct CARETINFO  select_start;
      struct CARETINFO  select_end;

      //끼워넣을 [공백문자열] 저장.
      char  tempStr[OPT_lineStrSize];

      //실제 처리할 시작행의 시작 위치.
      int   sLineStartIndex;

      //실제 처리할 끝행의 시작 위치.
      int   eLineStartIndex;

      int   i;

      //[2012.01.30.월][추가!!!]
      int   delta_caret_x;

      //[2012.02.02.목][추가!!!]
      //총 변화된 공백수를 기록.
      int   changeSize;

      //[2012.06.11.월][추가!!!]
      //<_CommentBlock_Info()> 의 결과를 보관.
      bool   cmtBlkChanged = false;

  //}

  //[선택 영역 정보 얻기]
  //{
      //[2012.01.30.월][추가!!!]{----------------------------------------
      //선택 영역 정보를 작은 것이 [시작위치] 가 되도록 정리하여 얻는다.
      //}----------------------------------------------------------------

      _SELECT_Get_StartEndIndex(&select_start, &select_end);

  //}

  //[처리할 것이 있나?]
  //{
      //[!]{----------------------------------
      //처리할 영역이 없다면 처리하지 않는다.
      //}-------------------------------------

      if((select_start.caret_index == select_end.caret_index) ||
         (select_start.caret_index < 0) || (select_end.caret_index < 0)) return(false);

  //}

  //[추가할 공백이 있나?]
  //{
      //[!]{----------------------------------
      //추가할 공백이 없다면 처리하지 않는다.
      //}-------------------------------------

      if(pSpaceCount <= 0) return(false);

  //}

  //[영역 정보 얻기]
  //{
      //[!]{------------------------------------------------------------------
      //정확한 [시작행 시작위치] 와 [끝행 시작위치] 얻기.
      //이는 다음 처리에서 간단하게 바로 행의 시작위치만으로 처리하기 위한것.
      //}---------------------------------------------------------------------

      //시작행 시작위치 얻기.
      STR_Get_ThisLineStartIndex(_editbuf, select_start.caret_index, &sLineStartIndex);

      //끝행 시작위치 얻기.
      STR_Get_ThisLineStartIndex(_editbuf, select_end.caret_index, &eLineStartIndex);

  //}


  //[수정이력:정보수집]{*******************************************************
  //[2012.02.07.화][추가!!!]
  //[입력지정자] 위치는 혆재 위치가 아니라 복구시 사용할 위치로
  //[시작행:시작위치] 와 같은 값으로 설정.
  //이는 [되돌리기/되살리기] 에서 사용되는 [수평이동 복구] 전용 함수를 위한것.
  _history.mCaretIndex          = sLineStartIndex;
  //[시작행:시작위치] 기록.
  _history.mStartLineStartIndex = sLineStartIndex;
  //[수정전:끝행:시작위치] 기록.
  _history.mEndLineStartIndex   = eLineStartIndex;
  //[이동수] 기록.
  _history.mMoveCount           = pSpaceCount;
  //}**************************************************************************


  //[공백문자열 생성]
  //{
      //[!]{---------------------------
      //끼워넣을 공백 문자열을 만든다.
      //}------------------------------

      for(i = 0; i < pSpaceCount; i++) { tempStr[i] = ' '; }

      //문자열로 완성.
      tempStr[i] = '\0';

  //}

  //[수평이동]
  //{
      //[!]{------------------------------------------
      //지정영역의 문자열을 [오른쪽:수평이동] 시킨다.
      //}---------------------------------------------

      for(i = sLineStartIndex, changeSize = 0;
          //마지막 행까지 처리해야 한다.
          i <= eLineStartIndex;
         )
      {
        //[NULL 행인가?]
        //{
            //[2012.02.02.목][추가!!!]{-------------------------------------------------
            //현재 행이 아무 문자열도 없는 [NULL행] 인 경우는 처리하지 않는다.
            //
            //CRLF(0x0d0a) 만 있는 경우는 [첫문자:CR] 인지.
            //'\0' 로 문서 끝인 경우는 [첫문자:'\0'] 인지 확인한다.
            //
            //[<행시작위치> == <행끝위치>] 인 경우도 이 행은 [NULL행] 이 되지만
            //[행끝위치] 를 얻기 위하여 <STR_Get_ThisLineEndIndex()> 함수를 사용하는
            //경우는 처리시간이 증가할수 있으므로 직접 [문자검사] 하는 방법을 사용한다.
            //}-------------------------------------------------------------------------

            //[NULL행] 인 경우는 이 행은 무시한다.
            if((_editbuf[i] == 0x0d) || (_editbuf[i] == '\0')) goto lbNextLineInfo;

        //}

        //[<편집기정보:_linetop_startindex> 수정]
        //{
            //[중요!!!]{-------------------------------------------------------
            //현재 처리행의 첫 위치가 <_linetop_startindex> 보다 이전인 경우는
            //이 첫 위치에 [공백문자열] 을 끼워넣는 경우, 현재 [편집기] 에서
            //보이는 첫행의 시작위치 정보인 <_linetop_startindex> 이 추가된
            //[공백문자열] 길이 만큼 위치가 밀리게 되어 부정확해 지므로
            //정확한 정보로 수정해 줘야 한다.
            //
            //<_linetop_startindex> 정보는 <_EditBuf_Text()> 로 편집기를 다시
            //출력할때 반드시 사용되는 중요정보이므로 실시간으로 정확한 정보를
            //가지고 있어야 한다.
            //}----------------------------------------------------------------

            //현재 처리행의 시작위치는 <i> 값이므로 <i> 로 비교한다.
            if(i < _linetop_startindex)
            {
              //이 경우는 <i> 위치에 [공백문자열] 을 추가하는 경우 <_linetop_startindex>
              //위치가 변경되므로 정확한 값으로 수정한다.

              _linetop_startindex += pSpaceCount;

            }

        //}

        //[공백문자열 끼워넣기]
        //{
            //현재 행 시작위치에 지정공백수만큼 끼워넣는다.
            _EditBuf_LineStr_Insert(i, tempStr);

        //}

        //[끝행 시작 위치 수정]
        //{
            //[!]{------------------------------------------------
            //지정개수의 공백이 추가되었으므로 [끝행 시작위치] 를
            //이 증가크기만큼 수정해 준다.
            //
            //[2012.02.07.화][중요수정!!!!!!]------------------------------------------
            //[끝행] 까지 처리되므로 이 [끝행:시작위치] 는 수정하지 말아야 한다.
            //이는 <for()> 문 다음의 [수정이력:정보수집] 에서 <eLineStartIndex> 정보를
            //[수정후:끝행:시작위치] 값으로 사용하기 때문이다.
            //}------------------------------------------------------------------------

            //[끝행] 인 경우는 지금의 값이 올바른 [끝행:시작위치] 이므로 수정하지 않는다.
            if(i < eLineStartIndex)
            {
              eLineStartIndex += pSpaceCount;

            }

        //}

        //[수정된 공백수 기록]
        //{
            //[2012.02.02.목][추가!!!]{---------
            //현재까지 수정된 총 공백수를 기록.
            //}---------------------------------

            changeSize += pSpaceCount;

        //}

        lbNextLineInfo:

        //[다음행 시작위치 얻기]
        //{
            //실제적으로 <i> 는 여기서만 수정된다.
            //<반환값:false> 인 경우는 현재행이 마지막 행인 경우로 바로 종료한다.
            if(STR_Get_NextLineStartIndex(_editbuf, i, &i) == false) break;

        //}

      }

  //}


  //[수정이력:정보수집]{*******************************
  //[2012.02.07.화][추가!!!]
  //[수정후:끝행:시작위치] 정보 기록.
  _history.mEndLineStartIndex_moved = eLineStartIndex;
  //}**************************************************


  //[입력지정자 위치 정보 수정]
  //{
      //[2012.01.30.월][추가!!!]{--------------------------------------
      //변경된 [입력지정자] 위치를 계산한다.
      //순서에 상관없으므로 [원본선택영역] 이 아닌 [크기순으로 정리된]
      //정보를 사용한다.
      //
      //1) [입력지정자] 위치가 [선택영역] 의 [작은위치] 와 같다.
      //   => { [입력지정자위치] += [공백수]; }
      //
      //2) [입력지정자] 위치가 [선택영역] 의 [큰위치] 와 같다.
      //   => { [입력지정자위치] += [공백수*처리총행수]; }
      //
      //[주의!!!]------------------------------------------------------
      //이 위치 전에 <_caretindex> 이 수정되지 않았어야 한다.
      //반드시 [크기순으로 정리된:선택영역정보] 를 사용한다.
      //}--------------------------------------------------------------

      //[정보:<_caretindex>]
      //{
          if(_caretindex == select_start.caret_index)
          {
            //[2012.02.04.토][중요수정!!!]{--------------------------------------------
            //[NULL행] 인 경우는 변화가 없으므로 [입력지정자:위치] 를 수정하지 않는다.
            //}------------------------------------------------------------------------

            if(!((_editbuf[_caretindex] == 0x0d) || (_editbuf[_caretindex] == '\0')))
            {
              _caretindex += pSpaceCount;

            }

          }
          else
          {
            //수정된 총 공백수를 더한다.
            _caretindex += changeSize;

          }

      //}

      //[입력 지정자 위치행 <시작/끝>]
      //{
          STR_Get_ThisLineStartIndex(_editbuf, _caretindex, &_linestartindex);
          STR_Get_ThisLineEndIndex(_editbuf, _linestartindex, &_lineendindex);

      //}

      //[정보:<_caretindexwidth>]
      //{
          //[참고!!!]{-------------------------------------------------------------------------
          //<_caretindex> 정보로 <_caretindexwidth> 정보와 부가 정보를 얻는다.
          //이 함수 끝에서 [입력지정자] 위치를 다시 조정하기 위하여 사용하는
          //<_EDIT_CaretPos()> 함수 안에서 <_Edit_Col()> 이 사용되고 다시 이 함수 안에서
          //<_CARETINDEX_CaretIndexWidth()> 가 사용되어 <_caretindexwidth> 와 <_col> 등
          //정보가 구해지지만, [선택영역 정보 수정] 을 위하여 이 위치에서도 계산한다.
          _CARETINDEX_CaretIndexWidth(_linestartindex, _caretindex, &_caretindexwidth, &_col);
          //}----------------------------------------------------------------------------------

          //<_caret_x> 의 [변화량] 계산(양수).
          //[오른쪽 수평이동] 이므로 새 위치는 이전 위치보다 오른쪽에 존재한다.
          delta_caret_x = _caretindexwidth - _caret_x;

          //새 위치로 수정.
          //[수평이동] 이므로 <_caret_y> 는 수정할 필요 없다.
          _caret_x  = _caretindexwidth;

      //}

  //}

  //[선택영역 정보 수정]
  //{
      //[2012.01.30.월][추가!!!]{----------------------------------
      //[원본:선택 영역 정보] 를 수정.
      //[원본] 정보이므로 [순방향/역방향] 의 경우를 구분하여 처리.
      //[수평이동] 이므로 <caret_y> 는 그대로 두고
      //<caretindex>, <caret_x> 만 수정하면 된다.
      //}----------------------------------------------------------

      if     (_select_start.caret_index < _select_end.caret_index)
      {
        //[순방향] 인 경우.

        //[2012.02.04.토][중요수정!!!]
        //[NULL행] 인 경우는 변화가 없으므로 다른 정보도 수정해서는 안된다.
        if(!((_editbuf[_select_start.caret_index] == 0x0d) || (_editbuf[_select_start.caret_index] == '\0')))
        {
          _select_start.caret_index += pSpaceCount;
          _select_start.caret_x     += delta_caret_x;

        }

        //이 경우는 [변화량] 만큼 수정되므로 [NULL행] 을 구분하지 않고 그대로 둔다.
        _select_end.caret_index += changeSize;
        _select_end.caret_x     += delta_caret_x;

      }
      else if(_select_start.caret_index > _select_end.caret_index)
      {
        //[역방향] 인 경우.

        //[2012.02.04.토][중요수정!!!]
        //[NULL행] 인 경우는 변화가 없으므로 다른 정보도 수정해서는 안된다.
        if(!((_editbuf[_select_end.caret_index] == 0x0d) || (_editbuf[_select_end.caret_index] == '\0')))
        {
          _select_end.caret_index += pSpaceCount;
          _select_end.caret_x     += delta_caret_x;

        }

        //이 경우는 [변화량] 만큼 수정되므로 [NULL행] 을 구분하지 않고 그대로 둔다.
        _select_start.caret_index += changeSize;
        _select_start.caret_x     += delta_caret_x;

      }

  //}

  //[묶음주석 정보 얻기]
  //{
      //[!]{------------------------------------------------------------------------
      //편집기 문자열이 대량으로 수정되었으므로 [묶음주석] 정보를 다시 얻어야 한다.
      //
      //[2012.06.11.월][설명!!!]----------------------------------------------------
      //[수정] 된후이고 [다시 그리기] 전에 수집.
      //}---------------------------------------------------------------------------

      //[2012.06.12.화][수정!!!]
      //부분정보 수집--------------------v
      cmtBlkChanged = _CommentBlock_Info(true);

  //}

  //[수정 반영]
  //{
      //항상 가장 마지막에 다시 보기 처리 한다.
      _EditBuf_Text();

  //}

  //[입력지정자]
  //{
      //[2012.01.31.화][추가!!!]{---------------------------------------------------
      //최종적으로 [선택영역] 을 유지한 채로 [입력지정자] 를 수정위치로 이동시킨다.
      //이는 현재 [선택영역] 을 계속 [수평이동] 하는 경우를 위한 것.
      //}---------------------------------------------------------------------------

      //[선택영역] 이 해제 되지 않도록 유지한다.
      _scroll_ing = true;
      //{
          //[문서원점] 이 수정되었으므로 [입력지정자] 위치도 다시 설정한다.
          _EDIT_CaretPos(_caret_x, _caret_y);

      //}
      _scroll_ing = false;

  //}


  //[수정이력:등록]{************************************
  //[2012.02.07.화][추가!!!]
  //[수평이동:오른쪽] 으로 인한 수정임을 등록.
  History_MoveRL_Add('>',
                     _history.mCaretIndex,
                     _history.mStartLineStartIndex,
                     _history.mEndLineStartIndex,
                     _history.mEndLineStartIndex_moved,
                     _history.mMoveCount);
  //}***************************************************

  //[문서수정]
  //{
      //[2012.02.01.수][추가!!!]{---
      //문서가 수정됐음을 기록.
      //}---------------------------

      _EDIT_Changed(false, true);

  //}

  return(true);

}

bool __fastcall Teditor_edit_Form::_LineBlock_MoveRL_Left(//삭제할 공백수.
                                                          int  pSpaceCount)
{
  //[2012.02.01.수][생성!!!]{----------------------------------------------------
  //[지정영역] 의 문자열의 각 행 시작 부분에서 지정수의 [공백] 을 삭제한다.
  //
  //<_LineBlock_Move_Rightt()> 함수를 먼저 만들었으며, 이를 참고로 만든 것으로
  //자세한 설명은 <_LineBlock_Move_Rightt()> 함수를 참고한다.
  //
  //[차이점!!!]------------------------------------------------------------------
  //[오른쪽 이동] 에는 [제한] 이 없지만, [왼쪽 이동] 시에는
  //[선택영역] 중 [최소 크기 행앞전 공백] 보다 작은 크기로 이동할수 없다.
  //즉, 더이상 앞에 공백이 없는 행이 한개라도 있으면 [왼쪽 이동] 은 안된다.
  //
  //<_LineBlock_Move_Rightt()> 와는 달리 이를 위하여 가장 처음에 [선택영역] 안
  //모든 행의 [최소 앞전 공백수] 를 먼저 구해야 한다.
  //
  //[2012.02.02.목][중요수정!!!]-------------------------------------------------
  //아무 문자가 없는 [NULL행] 인 경우는 수평이동 하지 않고 그대로 둔다.
  //이는 [오른쪽/왼쪽:수평이동] 시 조건을 동일하게 하기 위한것.
  //
  //[2012.02.04.토][중요수정!!!]-------------------------------------------------
  //[NULL행] 인 경우 변화가 없으므로, [입력지정자] 와 [선택영역] 도 역시 이
  //규칙에 따라 해당 행이 [NULL행] 에 해당하는 경우는 [정보] 를 수정하지 않는다.
  //
  //[2012.02.07.화][중요추가!!!]-------------------------------------------------
  //[수정이력] 등록 처리 추가.
  //}----------------------------------------------------------------------------

  //[VAR]
  //{
      //[선택영역] 정보를 순서대로 얻기 위한것.
      struct CARETINFO  select_start;
      struct CARETINFO  select_end;

      //실제 처리할 시작행의 시작 위치.
      int   sLineStartIndex;

      //실제 처리할 끝행의 시작 위치.
      int   eLineStartIndex;

      int   i;

      int   delta_caret_x;

      //[2012.02.01.수][추가!!!]{-----------------------
      //왼쪽으로 이동할수 있는 [최소 공백수] 를 가진다.
      //실제는 [선택영역 최소 앞전 공백수] 와 같다.
      int   min;
      //}-----------------------------------------------

      //[2012.02.02.목][추가!!!]
      //총 변화된 공백수를 기록.
      int   changeSize;

      //[2012.06.11.월][추가!!!]
      //<_CommentBlock_Info()> 의 결과를 보관.
      bool   cmtBlkChanged = false;

  //}

  //[선택 영역 정보 얻기]
  //{
      //[2012.01.30.월][추가!!!]{----------------------------------------
      //선택 영역 정보를 작은 것이 [시작위치] 가 되도록 정리하여 얻는다.
      //}----------------------------------------------------------------

      _SELECT_Get_StartEndIndex(&select_start, &select_end);

  //}

  //[처리할 것이 있나?]
  //{
      //[!]{----------------------------------
      //처리할 영역이 없다면 처리하지 않는다.
      //}-------------------------------------

      if((select_start.caret_index == select_end.caret_index) ||
         (select_start.caret_index < 0) || (select_end.caret_index < 0)) return(false);

  //}

  //[삭제할 공백이 있나?]
  //{
      //[!]{----------------------------------
      //추가할 공백이 없다면 처리하지 않는다.
      //}-------------------------------------

      if(pSpaceCount <= 0) return(false);

  //}

  //[선택영역 최소 앞전 공백수 얻기]
  //{
      //[2012.02.02.목][추가!!!]{----------------------------------------
      //[선택영역] 안의 모든 행을 대상으로 [최소 앞전 공백수] 를 얻는다.
      //이는 더이상 이동할수 없는 공백수를 얻기 위한것.
      //
      //보다 고속 처리를 위하여 새로 만든 함수를 사용한다.
      //}----------------------------------------------------------------

      //[2012.02.02.목] 에 새로 만드느 함수를 사용.
      min = Str_Get_LinePreSpaceCount_Min(_editbuf,
                                          select_start.caret_index,
                                          select_end.caret_index,
                                          //NULL 행은 제외.
                                          true);

  //}

  //[왼쪽 이동 가능한가?]
  //{
      //[2012.02.01.수][추가!!!]{----------------------------------
      //[이동공백수] 가 [최소공백수] 를 넘는 경우는 이동할수 없다.
      //이 경우는 [오류] 임을 보여주고 이동하지 않는 것으로 한다.
      //}----------------------------------------------------------

      if(pSpaceCount > min)
      {
        //[!]{------------------------------------------------
        //이 경우는 이동공백수를 초과한 경우도 처리 불가하다.
        //더이상 처리하지 않는다.
        //}---------------------------------------------------

        return(false);

      }

  //}

  //[영역 정보 얻기]
  //{
      //[!]{------------------------------------------------------------------
      //정확한 [시작행 시작위치] 와 [끝행 시작위치] 얻기.
      //이는 다음 처리에서 간단하게 바로 행의 시작위치만으로 처리하기 위한것.
      //}---------------------------------------------------------------------

      //시작행 시작위치 얻기.
      STR_Get_ThisLineStartIndex(_editbuf, select_start.caret_index, &sLineStartIndex);

      //끝행 시작위치 얻기.
      STR_Get_ThisLineStartIndex(_editbuf, select_end.caret_index, &eLineStartIndex);

  //}


  //[수정이력:정보수집]{*******************************************************
  //[2012.02.07.화][추가!!!]
  //[입력지정자] 위치는 혆재 위치가 아니라 복구시 사용할 위치로
  //[시작행:시작위치] 와 같은 값으로 설정.
  //이는 [되돌리기/되살리기] 에서 사용되는 [수평이동 복구] 전용 함수를 위한것.
  _history.mCaretIndex          = sLineStartIndex;
  //[시작행:시작위치] 기록.
  _history.mStartLineStartIndex = sLineStartIndex;
  //[수정전:끝행:시작위치] 기록.
  _history.mEndLineStartIndex   = eLineStartIndex;
  //[이동수] 기록.
  _history.mMoveCount           = pSpaceCount;
  //}**************************************************************************


  //[수평이동]
  //{
      //[!]{--------------------------------------------------------------------
      //지정영역의 문자열을 [왼쪽:수평이동] 시킨다.
      //
      //지정 위치부터 지정수만큼 행의 시작 위치 공백을 삭제하는 것이므로
      //금일 이 목적으로 새로 만든 <_EditBuf_LineStr_Delete()> 함수를 사용한다.
      //}-----------------------------------------------------------------------

      for(i = sLineStartIndex, changeSize = 0;
          //마지막 행까지 처리해야 한다.
          i <= eLineStartIndex;
         )
      {
        //[NULL 행인가?]
        //{
            //[2012.02.02.목][추가!!!]{-------------------------------------------------
            //현재 행이 아무 문자열도 없는 [NULL행] 인 경우는 처리하지 않는다.
            //
            //CRLF(0x0d0a) 만 있는 경우는 [첫문자:CR] 인지.
            //'\0' 로 문서 끝인 경우는 [첫문자:'\0'] 인지 확인한다.
            //
            //[<행시작위치> == <행끝위치>] 인 경우도 이 행은 [NULL행] 이 되지만
            //[행끝위치] 를 얻기 위하여 <STR_Get_ThisLineEndIndex()> 함수를 사용하는
            //경우는 처리시간이 증가할수 있으므로 직접 [문자검사] 하는 방법을 사용한다.
            //}-------------------------------------------------------------------------

            //[NULL행] 인 경우 이 행은 무시한다.
            if((_editbuf[i] == 0x0d) || (_editbuf[i] == '\0')) goto lbNextLineInfo;

        //}

        //[<편집기정보:_linetop_startindex> 수정]
        //{
            //[중요!!!]{-------------------------------------------------------
            //현재 처리행의 첫 위치가 <_linetop_startindex> 보다 이전인 경우는
            //이 첫 위치에 [공백문자열] 을 끼워넣는 경우, 현재 [편집기] 에서
            //보이는 첫행의 시작위치 정보인 <_linetop_startindex> 이 추가된
            //[공백문자열] 길이 만큼 위치가 밀리게 되어 부정확해 지므로
            //정확한 정보로 수정해 줘야 한다.
            //
            //<_linetop_startindex> 정보는 <_EditBuf_Text()> 로 편집기를 다시
            //출력할때 반드시 사용되는 중요정보이므로 실시간으로 정확한 정보를
            //가지고 있어야 한다.
            //}----------------------------------------------------------------

            //현재 처리행의 시작위치는 <i> 값이므로 <i> 로 비교한다.
            if(i < _linetop_startindex)
            {
              //이 경우는 <i> 위치에 [공백문자열] 을 [삭제] 하는 경우 <_linetop_startindex>
              //위치가 변경되므로 정확한 값으로 수정한다.

              _linetop_startindex -= pSpaceCount;

            }

        //}

        //[지정수 앞전 공백 삭제]
        //{
            //현재 행 시작위치에서 지정공백수만큼 삭제.
            _EditBuf_LineStr_Delete(i, pSpaceCount);

        //}

        //[끝행 시작 위치 수정]
        //{
            //[!]{---------------------------------------------------------------------
            //지정개수의 공백이 [삭제] 되었으므로 [끝행 시작위치] 를
            //이 [감소] 크기만큼 수정해 준다.
            //
            //[2012.02.07.화][중요수정!!!!!!]------------------------------------------
            //[끝행] 까지 처리되므로 이 [끝행:시작위치] 는 수정하지 말아야 한다.
            //이는 <for()> 문 다음의 [수정이력:정보수집] 에서 <eLineStartIndex> 정보를
            //[수정후:끝행:시작위치] 값으로 사용하기 때문이다.
            //}------------------------------------------------------------------------

            //[끝행] 인 경우는 지금의 값이 올바른 [끝행:시작위치] 이므로 수정하지 않는다.
            if(i < eLineStartIndex)
            {
              eLineStartIndex -= pSpaceCount;

            }

        //}

        //[수정된 공백수 기록]
        //{
            //[2012.02.02.목][추가!!!]{---------
            //현재까지 수정된 총 공백수를 기록.
            //}---------------------------------

            changeSize += pSpaceCount;

        //}

        lbNextLineInfo:

        //[다음행 시작위치 얻기]
        //{
            //실제적으로 <i> 는 여기서만 수정된다.
            //<반환값:false> 인 경우는 현재행이 마지막 행인 경우로 바로 종료한다.
            if(STR_Get_NextLineStartIndex(_editbuf, i, &i) == false) break;

        //}

      }

  //}


  //[수정이력:정보수집]{*******************************
  //[2012.02.07.화][추가!!!]
  //[수정후:끝행:시작위치] 정보 기록.
  _history.mEndLineStartIndex_moved = eLineStartIndex;
  //}**************************************************


  //[입력지정자 위치 정보 수정]
  //{
      //[!]{-----------------------------------------------------------
      //변경된 [입력지정자] 위치를 계산한다.
      //순서에 상관없으므로 [원본선택영역] 이 아닌 [크기순으로 정리된]
      //정보를 사용한다.
      //
      //1) [입력지정자] 위치가 [선택영역] 의 [작은위치] 와 같다.
      //   => { [입력지정자위치] += [공백수]; }
      //
      //2) [입력지정자] 위치가 [선택영역] 의 [큰위치] 와 같다.
      //   => { [입력지정자위치] += [공백수*처리총행수]; }
      //
      //[주의!!!]------------------------------------------------------
      //이 위치 전에 <_caretindex> 이 수정되지 않았어야 한다.
      //반드시 [크기순으로 정리된:선택영역정보] 를 사용한다.
      //}--------------------------------------------------------------

      //[정보:<_caretindex>]
      //{
          if(_caretindex == select_start.caret_index)
          {
            //[2012.02.04.토][중요수정!!!]{--------------------------------------------
            //[NULL행] 인 경우는 변화가 없으므로 [입력지정자:위치] 를 수정하지 않는다.
            //}------------------------------------------------------------------------

            if(!((_editbuf[_caretindex] == 0x0d) || (_editbuf[_caretindex] == '\0')))
            {
              if(_caretindex == sLineStartIndex)
              {
                //[2012.03.02.금][중요추가!!!]{---------------------------------------
                //[입력지정자위치] 가 현재 위치한 행을 벗어나서는 안되므로
                //[현재행:시작위치] 로 고정.
                //이상태를 그대로 두면 [이전행] 의 CRLF 중 [LF] 위치에 존재하게 된다.
                //}-------------------------------------------------------------------

                _caretindex = sLineStartIndex;

              }
              else
              {
                _caretindex -= pSpaceCount;

              }

            }

          }
          else
          {
            if(eLineStartIndex > (_caretindex - changeSize))
            {
              //[2012.03.02.금][중요추가!!!]{---------------------------------------
              //[입력지정자위치] 가 현재 위치한 행을 벗어나서는 안되므로
              //[현재행:시작위치] 로 고정.
              //이상태를 그대로 두면 [이전행] 의 CRLF 중 [LF] 위치에 존재하게 된다.
              //}-------------------------------------------------------------------

              _caretindex = eLineStartIndex;

            }
            else
            {
              //수정된 총 공백수를 뺀다.
              _caretindex -= changeSize;

            }

          }

      //}

      //[입력 지정자 위치행 <시작/끝>]
      //{
          STR_Get_ThisLineStartIndex(_editbuf, _caretindex, &_linestartindex);
          STR_Get_ThisLineEndIndex(_editbuf, _linestartindex, &_lineendindex);

      //}

      //[정보:<_caretindexwidth>]
      //{
          //[참고!!!]{-------------------------------------------------------------------------
          //<_caretindex> 정보로 <_caretindexwidth> 정보와 부가 정보를 얻는다.
          //이 함수 끝에서 [입력지정자] 위치를 다시 조정하기 위하여 사용하는
          //<_EDIT_CaretPos()> 함수 안에서 <_Edit_Col()> 이 사용되고 다시 이 함수 안에서
          //<_CARETINDEX_CaretIndexWidth()> 가 사용되어 <_caretindexwidth> 와 <_col> 등
          //정보가 구해지지만, [선택영역 정보 수정] 을 위하여 이 위치에서도 계산한다.
          _CARETINDEX_CaretIndexWidth(_linestartindex, _caretindex, &_caretindexwidth, &_col);
          //}----------------------------------------------------------------------------------

          //<_caret_x> 의 [변화량] 계산(양수).
          //[왼쪽 수평이동] 이므로 새 위치는 이전 위치보다 오른쪽에 존재한다.
          delta_caret_x = _caret_x - _caretindexwidth;

          //새 위치로 수정.
          //[수평이동] 이므로 <_caret_y> 는 수정할 필요 없다.
          _caret_x  = _caretindexwidth;

      //}

  //}

  //[선택영역 정보 수정]
  //{
      //[2012.01.30.월][추가!!!]{---------------------------------------------------
      //[원본:선택 영역 정보] 를 수정.
      //[원본] 정보이므로 [순방향/역방향] 의 경우를 구분하여 처리.
      //[수평이동] 이므로 <caret_y> 는 그대로 두고
      //<caretindex>, <caret_x> 만 수정하면 된다.
      //
      //[2012.03.02.금][중요수정!!!]------------------------------------------------
      //[선택영역] 의 [시작/끝] 위치가 [행의 시작위치] 인 경우는 더이상 [왼쪽] 으로
      //이동하면 안되므로 위치를 바꾸면 안된다.
      //즉, 더이상 [왼쪽] 으로 이동이 불가능할 경우 각 [행:시작위치] 를 할당.
      //이는 [오른쪽 수평이동] 시에는 고려할 필요가 없다.
      //}---------------------------------------------------------------------------

      if     (_select_start.caret_index < _select_end.caret_index)
      {
        //[순방향] 인 경우.

        //[시작위치]
        //{
            //[2012.02.04.토][중요수정!!!]
            //[NULL행] 인 경우는 변화가 없으므로 다른 정보도 수정해서는 안된다.
            if(!((_editbuf[_select_start.caret_index] == 0x0d) || (_editbuf[_select_start.caret_index] == '\0')))
            {
              if(sLineStartIndex == _select_start.caret_index)
              {
                //[2012.03.02.금][중요수정!!!]{---------------------------------
                //{ [선택영역:시작위치] == [시작행:시작위치] } 인 경우는 더이상
                //[왼쪽] 으로 이동할수 없으므로 [행:시작위치] 로 재설정.
                //}-------------------------------------------------------------

                _select_start.caret_index = sLineStartIndex;

                //행의 처음 위치에서는 항상 0.
                _select_start.caret_x     = 0;

              }
              else
              {
                _select_start.caret_index -= pSpaceCount;
                _select_start.caret_x     -= delta_caret_x;

              }

            }

        //}

        //[끝위치]
        //{
            if(eLineStartIndex > (_select_end.caret_index - changeSize))
            {
              //[2012.03.02.금][중요수정!!!]{-----------------------------
              //{ [선택영역:끝위치] == [끝행:시작위치] } 인 경우는 더이상
              //[왼쪽] 으로 이동할수 없으므로 [행:시작위치] 로 재설정.
              //}---------------------------------------------------------

              //이 경우는 [변화량] 만큼 수정되므로 [NULL행] 을 구분하지 않고 그대로 둔다.
              _select_end.caret_index = eLineStartIndex;

              //행의 처음 위치에서는 항상 0.
              _select_end.caret_x     = 0;

            }
            else
            {
              //이 경우는 [변화량] 만큼 수정되므로 [NULL행] 을 구분하지 않고 그대로 둔다.
              _select_end.caret_index -= changeSize;
              _select_end.caret_x     -= delta_caret_x;


            }

        //}

      }
      else if(_select_start.caret_index > _select_end.caret_index)
      {
        //[역방향] 인 경우.

        //[끝위치]
        //{
            //[2012.02.04.토][중요수정!!!]
            //[NULL행] 인 경우는 변화가 없으므로 다른 정보도 수정해서는 안된다.
            if(!((_editbuf[_select_end.caret_index] == 0x0d) || (_editbuf[_select_end.caret_index] == '\0')))
            {
              if(sLineStartIndex == _select_end.caret_index)
              {
                //[2012.03.02.금][중요수정!!!]{---------------------------------
                //{ [선택영역:시작위치] == [시작행:시작위치] } 인 경우는 더이상
                //[왼쪽] 으로 이동할수 없으므로 [행:시작위치] 로 재설정.
                //}-------------------------------------------------------------

                _select_end.caret_index = sLineStartIndex;

                //행의 처음 위치에서는 항상 0.
                _select_end.caret_x     = 0;

              }
              else
              {
                _select_end.caret_index -= pSpaceCount;
                _select_end.caret_x     -= delta_caret_x;

              }

            }

        //}

        //[시작위치]
        //{
            if(eLineStartIndex > (_select_start.caret_index - changeSize))
            {
              //[2012.03.02.금][중요수정!!!]{-----------------------------
              //{ [선택영역:끝위치] == [끝행:시작위치] } 인 경우는 더이상
              //[왼쪽] 으로 이동할수 없으므로 [행:시작위치] 로 재설정.
              //}---------------------------------------------------------

              //이 경우는 [변화량] 만큼 수정되므로 [NULL행] 을 구분하지 않고 그대로 둔다.
              _select_start.caret_index = eLineStartIndex;

              //행의 처음 위치에서는 항상 0.
              _select_start.caret_x     = 0;

            }
            else
            {
              //이 경우는 [변화량] 만큼 수정되므로 [NULL행] 을 구분하지 않고 그대로 둔다.
              _select_start.caret_index -= changeSize;
              _select_start.caret_x     -= delta_caret_x;


            }

        //}

      }

  //}

  //[묶음주석 정보 얻기]
  //{
      //[!]{------------------------------------------------------------------------
      //편집기 문자열이 대량으로 수정되었으므로 [묶음주석] 정보를 다시 얻어야 한다.
      //
      //[2012.06.11.월][설명!!!]----------------------------------------------------
      //[수정] 된후이고 [다시 그리기] 전에 수집.
      //}---------------------------------------------------------------------------

      //[2012.06.12.화][수정!!!]
      //부분정보 수집--------------------v
      cmtBlkChanged = _CommentBlock_Info(true);

  //}

  //[수정 반영]
  //{
      //항상 가장 마지막에 다시 보기 처리 한다.
      _EditBuf_Text();

  //}

  //[입력지정자]
  //{
      //[2012.01.31.화][추가!!!]{---------------------------------------------------
      //최종적으로 [선택영역] 을 유지한 채로 [입력지정자] 를 수정위치로 이동시킨다.
      //이는 현재 [선택영역] 을 계속 [수평이동] 하는 경우를 위한 것.
      //}---------------------------------------------------------------------------

      //[선택영역] 이 해제 되지 않도록 유지한다.
      _scroll_ing = true;
      //{
          //[문서원점] 이 수정되었으므로 [입력지정자] 위치도 다시 설정한다.
          _EDIT_CaretPos(_caret_x, _caret_y);

      //}
      _scroll_ing = false;

  //}


  //[수정이력:등록]{************************************
  //[2012.02.07.화][추가!!!]
  //[수평이동:왼쪽] 으로 인한 수정임을 등록.
  History_MoveRL_Add('<',
                     _history.mCaretIndex,
                     _history.mStartLineStartIndex,
                     _history.mEndLineStartIndex,
                     _history.mEndLineStartIndex_moved,
                     _history.mMoveCount);
  //}***************************************************

  //[문서수정]
  //{
      //[2012.02.01.수][추가!!!]{---
      //문서가 수정됐음을 기록.
      //}---------------------------

      _EDIT_Changed(false, true);

  //}

  return(true);

}

void __fastcall Teditor_edit_Form::History_MoveRL_Right(//설정할 [입력지정자] 위치.
                                                        int  pCaretIndex,
                                                        //처리할 [시작행 시작위치].
                                                        int  pStartLineStartIndex,
                                                        //처리할 [끝행 시작위치].
                                                        int  pEndLineStartIndex,
                                                        //이동할 공백수.
                                                        int  pSpaceCount)
{
  //[2012.02.04.토][생성!!!]{--------------------------------------------------------------------
  //<_LineBlock_MoveRL_Right()> 함수와 거의 동일한 기능이나, [수평이동:왼쪽] 을 [수정이력] 에서
  //복구할때 사용하며, [선택영역] 없이 바로 사용한다.
  //
  //단, [선택영역] 이 존재하는 상황이라면 먼저 [선택영역] 부터 해제시킨다.
  //이는 모든 [되돌리기/되살리기] 의 기본 사전 동작이다.
  //
  //또한, <_linetop_startindex> 값등 내부적으로 [편집기 정보] 를 수정해 주어야 하는 것이 없도록
  //[이동 시작행 첫위치] 에 항상 [입력지정자] 를 놓고 시작한다.
  //단, 반드시 [입력지정자 보이기] 상태로 만들어야 한다.
  //즉, 항상 [시작행 첫위치] 와 [입력지정자] 가 [편집기:보이는영역] 에 존재하는 상태로 시작한다.
  //
  //[주의!!!]------------------------------------------------------------------------------------
  //[편집기 정보] 중에서는 <_filesize> 만 직접 수정된다.
  //}--------------------------------------------------------------------------------------------

  //[방법!!!]**************************************************
  //
  //1) [선택영역] 해제.
  //
  //2) [입력지정자] 를 [처리시작행 시작위치] 에 위치.
  //   [입력지정자] 는 항상 [편집기:보이는영역] 에 위치시킨다.
  //
  //3) [오른쪽 수평이동] 처리.
  //
  //}**********************************************************

  //[VAR]
  //{
      //끼워넣을 [공백문자열] 저장.
      char  tempStr[OPT_lineStrSize];

      int   i;

      //총 변화된 공백수를 기록.
      int   changeSize;

      //[2012.06.11.월][추가!!!]
      //<_CommentBlock_Info()> 의 결과를 보관.
      bool   cmtBlkChanged = false;

  //}

  //[참고!!!]{------------------------------------------------
  //[되돌리기/되살리기] 용이므로 반드시 처리할 것이 존재한다.
  //}---------------------------------------------------------

  //[<선택영역:해제> 와 <입력지정자 위치설정>]
  //{
      //[!]{-------------------------------------------------------------------
      //<History_SetCaretPos()> 안에서 자동으로 [선택영역 해제] 까지 처리된다.
      //}----------------------------------------------------------------------

      //[입력지정자] 를 지정 위치로 이동 시키고, [편집기 보이는 영역] 에 위치시킨다.
      //[보이는 영역] 에 위치-----------v
       History_SetCaretPos(pCaretIndex, true);

  //}

  //[공백문자열 생성]
  //{
      //[!]{---------------------------
      //끼워넣을 공백 문자열을 만든다.
      //}------------------------------

      for(i = 0; i < pSpaceCount; i++) { tempStr[i] = ' '; }

      //문자열로 완성.
      tempStr[i] = '\0';

  //}

  //[수평이동]
  //{
      //[!]{------------------------------------------
      //지정영역의 문자열을 [오른쪽:수평이동] 시킨다.
      //}---------------------------------------------

      for(i = pStartLineStartIndex, changeSize = 0;
          //마지막 행까지 처리해야 한다.
          i <= pEndLineStartIndex;
         )
      {
        //[NULL 행인가?]
        //{
            //[!]{----------------------------------------------------------------------
            //현재 행이 아무 문자열도 없는 [NULL행] 인 경우는 처리하지 않는다.
            //
            //CRLF(0x0d0a) 만 있는 경우는 [첫문자:CR] 인지.
            //'\0' 로 문서 끝인 경우는 [첫문자:'\0'] 인지 확인한다.
            //
            //[행시작위치 ==  행끝위치] 인 경우도 이 행은 [NULL행] 이 되지만
            //[행끝위치] 를 얻기 위하여 <STR_Get_ThisLineEndIndex()> 함수를 사용하는
            //경우는 처리시간이 증가할수 있으므로 직접 [문자검사] 하는 방법을 사용한다.
            //}-------------------------------------------------------------------------

            //[NULL행] 인 경우는 이 행은 무시한다.
            if((_editbuf[i] == 0x0d) || (_editbuf[i] == '\0')) goto lbNextLineInfo;

        //}

        //[<편집기정보:_linetop_startindex> 수정]
        //{
            //[중요!!!]{----------------------------------------------------------------
            //이미 [시작위치] 가 [편집기 보이는 영역] 에 존재하므로 처리할 필요가 없다.
            //}-------------------------------------------------------------------------

        //}

        //[공백문자열 끼워넣기]
        //{
            //현재 행 시작위치에 지정공백수만큼 끼워넣는다.
            _EditBuf_LineStr_Insert(i, tempStr);

        //}

        //[끝행 시작 위치 수정]
        //{
            //[!]{------------------------------------------------
            //지정개수의 공백이 추가되었으므로 [끝행 시작위치] 를
            //이 증가크기만큼 수정해 준다.
            //}---------------------------------------------------

            pEndLineStartIndex += pSpaceCount;

        //}

        //[수정된 공백수 기록]
        //{
            //[!]{------------------------------
            //현재까지 수정된 총 공백수를 기록.
            //}---------------------------------

            changeSize += pSpaceCount;

        //}

        lbNextLineInfo:

        //[다음행 시작위치 얻기]
        //{
            //실제적으로 <i> 는 여기서만 수정된다.
            //<반환값:false> 인 경우는 현재행이 마지막 행인 경우로 바로 종료.
            if(STR_Get_NextLineStartIndex(_editbuf, i, &i) == false) break;

        //}

      }

  //}

  //[입력지정자 위치 정보 수정]
  //{
      //[!]{--------------------------------------
      //[입력지정자] 를 먼저 설정했으므로 불필요.
      //}-----------------------------------------

  //}

  //[선택영역 정보 수정]
  //{
      //[!]{------------------------------------
      //[선택영역] 은 먼저 해제했으므로 불필요.
      //}---------------------------------------

  //}

  //[묶음주석 정보 얻기]
  //{
      //[!]{------------------------------------------------------------------------
      //편집기 문자열이 대량으로 수정되었으므로 [묶음주석] 정보를 다시 얻어야 한다.
      //}---------------------------------------------------------------------------

      //[2012.06.12.화][수정!!!]
      //부분정보 수집--------------------v
      cmtBlkChanged = _CommentBlock_Info(true);

  //}

  //[수정 반영]
  //{
      //항상 가장 마지막에 다시 보기 처리 한다.
      _EditBuf_Text();

  //}

  //[문서수정]
  //{
      //[!]{--------------------
      //문서가 수정됐음을 기록.
      //}-----------------------

      _EDIT_Changed(false, true);

  //}

}

void __fastcall Teditor_edit_Form::History_MoveRL_Left(//설정할 [입력지정자] 위치.
                                                       int  pCaretIndex,
                                                       //처리할 [시작행 시작위치].
                                                       int  pStartLineStartIndex,
                                                       //처리할 [끝행 시작위치].
                                                       int  pEndLineStartIndex,
                                                       //이동할 공백수.
                                                       int  pSpaceCount)
{
  //[2012.02.05.일][생성!!!]{--------------------------------------------------------------------
  //<_LineBlock_MoveRL_Left()> 함수와 거의 동일한 기능이나, [수평이동:오른쪽] 을 [수정이력] 에서
  //복구할때 사용하며, [선택영역] 없이 바로 사용한다.
  //
  //단, [선택영역] 이 존재하는 상황이라면 먼저 [선택영역] 부터 해제시킨다.
  //이는 모든 [되돌리기/되살리기] 의 기본 사전 동작이다.
  //
  //또한, <_linetop_startindex> 값등 내부적으로 [편집기 정보] 를 수정해 주어야 하는 것이 없도록
  //[이동 시작행 첫위치] 에 항상 [입력지정자] 를 놓고 시작한다.
  //단, 반드시 [입력지정자 보이기] 상태로 만들어야 한다.
  //즉, 항상 [시작행 첫위치] 와 [입력지정자] 가 [편집기:보이는영역] 에 존재하는 상태로 시작한다.
  //
  //[주의!!!]------------------------------------------------------------------------------------
  //[편집기 정보] 중에서는 <_filesize> 만 직접 수정된다.
  //
  //[참고!!!]------------------------------------------------------------------------------------
  //<_LineBlock_MoveRL_Left()> 함수는 <Ctrl+Left]> 조합의 경우 동작되는 것으로 [왼쪽 이동 제한] 이
  //존재하지만 이 함수는 [수정이력] 용으로 이미 동작됐던 영역 만큼 이동하는 것이기 때문에
  //제한이 불필요하다.
  //그러나, 만일을 위하여 <_LineBlock_MoveRL_Left()> 와 동일하게 적용한다.
  //}--------------------------------------------------------------------------------------------

  //[방법!!!]**************************************************
  //
  //1) [선택영역] 해제.
  //
  //2) [입력지정자] 를 [처리시작행 시작위치] 에 위치.
  //   [입력지정자] 는 항상 [편집기:보이는영역] 에 위치시킨다.
  //
  //3) [왼쪽 수평이동] 처리.
  //
  //}**********************************************************

  //[VAR]
  //{
      //왼쪽으로 이동할수 있는 [최소 공백수] 를 가진다.
      //실제는 [선택영역 최소 앞전 공백수] 와 같다.
      int   min;

      int   i;

      //총 변화된 공백수를 기록.
      int   changeSize;

      //[2012.06.11.월][추가!!!]
      //<_CommentBlock_Info()> 의 결과를 보관.
      bool  cmtBlkChanged = false;

  //}

  //[참고!!!]{------------------------------------------------
  //[되돌리기/되살리기] 용이므로 반드시 처리할 것이 존재한다.
  //}---------------------------------------------------------

  //[<선택영역:해제> 와 <입력지정자 위치설정>]
  //{
      //[!]{-------------------------------------------------------------------
      //<History_SetCaretPos()> 안에서 자동으로 [선택영역 해제] 까지 처리된다.
      //}----------------------------------------------------------------------

      //[입력지정자] 를 지정 위치로 이동 시키고, [편집기 보이는 영역] 에 위치시킨다.
      //[보이는 영역] 에 위치-----------v
       History_SetCaretPos(pCaretIndex, true);

  //}

  //[선택영역 최소 앞전 공백수 얻기]
  //{
      //[!]{-------------------------------------------------------------
      //[선택영역] 안의 모든 행을 대상으로 [최소 앞전 공백수] 를 얻는다.
      //이는 더이상 이동할수 없는 공백수를 얻기 위한것.
      //
      //보다 고속 처리를 위하여 새로 만든 함수를 사용한다.
      //}----------------------------------------------------------------

      min = Str_Get_LinePreSpaceCount_Min(_editbuf,
                                          pStartLineStartIndex,
                                          pEndLineStartIndex,
                                          //NULL 행은 제외.
                                          true);

  //}

  //[왼쪽 이동 가능한가?]
  //{
      //[!]{-------------------------------------------------------
      //[이동공백수] 가 [최소공백수] 를 넘는 경우는 이동할수 없다.
      //이 경우는 [오류] 임을 보여주고 이동하지 않는 것으로 한다.
      //}----------------------------------------------------------

      if(pSpaceCount > min)
      {
        //[!]{------------------------------------------------
        //이 경우는 이동공백수를 초과한 경우도 처리 불가하다.
        //더이상 처리하지 않는다.
        //}---------------------------------------------------

        return;

      }

  //}

  //[수평이동]
  //{
      //[!]{--------------------------------------------------------------------
      //지정영역의 문자열을 [왼쪽:수평이동] 시킨다.
      //
      //지정 위치부터 지정수만큼 행의 시작 위치 공백을 삭제하는 것이므로
      //금일 이 목적으로 새로 만든 <_EditBuf_LineStr_Delete()> 함수를 사용한다.
      //}-----------------------------------------------------------------------

      for(i = pStartLineStartIndex, changeSize = 0;
          //마지막 행까지 처리해야 한다.
          i <= pEndLineStartIndex;
         )
      {
        //[NULL 행인가?]
        //{
            //[!]{----------------------------------------------------------------------
            //현재 행이 아무 문자열도 없는 [NULL행] 인 경우는 처리하지 않는다.
            //
            //CRLF(0x0d0a) 만 있는 경우는 [첫문자:CR] 인지.
            //'\0' 로 문서 끝인 경우는 [첫문자:'\0'] 인지 확인한다.
            //
            //[<행시작위치> == <행끝위치>] 인 경우도 이 행은 [NULL행] 이 되지만
            //[행끝위치] 를 얻기 위하여 <STR_Get_ThisLineEndIndex()> 함수를 사용하는
            //경우는 처리시간이 증가할수 있으므로 직접 [문자검사] 하는 방법을 사용한다.
            //}-------------------------------------------------------------------------

            //[NULL행] 인 경우는 이 행은 무시한다.
            if((_editbuf[i] == 0x0d) || (_editbuf[i] == '\0')) goto lbNextLineInfo;

        //}

        //[<편집기정보:_linetop_startindex> 수정]
        //{
            //[중요!!!]{----------------------------------------------------------------
            //이미 [시작위치] 가 [편집기 보이는 영역] 에 존재하므로 처리할 필요가 없다.
            //}-------------------------------------------------------------------------

        //}

        //[지정수 앞전 공백 삭제]
        //{
            //현재 행 시작위치에서 지정공백수만큼 삭제.
            _EditBuf_LineStr_Delete(i, pSpaceCount);

        //}

        //[끝행 시작 위치 수정]
        //{
            //[!]{---------------------------------------------------
            //지정개수의 공백이 [삭제] 되었으므로 [끝행 시작위치] 를
            //이 [감소] 크기만큼 수정해 준다.
            //}------------------------------------------------------

            pEndLineStartIndex -= pSpaceCount;

        //}

        //[수정된 공백수 기록]
        //{
            //[!]{------------------------------
            //현재까지 수정된 총 공백수를 기록.
            //}---------------------------------

            changeSize += pSpaceCount;

        //}

        lbNextLineInfo:

        //[다음행 시작위치 얻기]
        //{
            //실제적으로 <i> 는 여기서만 수정된다.
            //<반환값:false> 인 경우는 현재행이 마지막 행인 경우로 바로 종료한다.
            if(STR_Get_NextLineStartIndex(_editbuf, i, &i) == false) break;

        //}

      }

  //}

  //[입력지정자 위치 정보 수정]
  //{
      //[!]{--------------------------------------
      //[입력지정자] 를 먼저 설정했으므로 불필요.
      //}-----------------------------------------

  //}

  //[선택영역 정보 수정]
  //{
      //[!]{------------------------------------
      //[선택영역] 은 먼저 해제했으므로 불필요.
      //}---------------------------------------

  //}

  //[묶음주석 정보 얻기]
  //{
      //[!]{------------------------------------------------------------------------
      //편집기 문자열이 대량으로 수정되었으므로 [묶음주석] 정보를 다시 얻어야 한다.
      //}---------------------------------------------------------------------------

      //[2012.06.12.화][수정!!!]
      //부분정보 수집--------------------v
      cmtBlkChanged = _CommentBlock_Info(true);

  //}

  //[수정 반영]
  //{
      //항상 가장 마지막에 다시 보기 처리 한다.
      _EditBuf_Text();

  //}

  //[문서수정]
  //{
      //[!]{--------------------
      //문서가 수정됐음을 기록.
      //}-----------------------

      _EDIT_Changed(false, true);

  //}

}

void __fastcall Teditor_edit_Form::History_MoveRL_Add(//수평이동 종류('>', '<').
                                                      char  pKind,
                                                      //입력지정자 배치 위치(복구시 사용할 위치).
                                                      //[수평이동] 에서는 <pStartLineStartIndex> 와 같은값.
                                                      int   pCaretIndex,
                                                      //<시작행:시작위치>.
                                                      //이 위치는 수정 전/후 항상 같은 값으로 변하지 않는다.
                                                      int   pStartLineStartIndex,
                                                      //수정전 <끝행:시작위치>.
                                                      int   pEndLineStartIndex,
                                                      //수정후 <끝행:시작위치>.
                                                      int   pEndLineStartIndex_moved,
                                                      //이동할 간격.
                                                      int   pMoveCount)
{
  //[2012.02.06.월][생성!!!]{----------------------------------------------------
  //[수평이동] 의 [수정이력 추가] 를 처리.
  //[수평이동] 의 경우는 [기본편집] 과 [수정이력] 이 [첫번째/두번째] 정보 이외에
  //완전히 다르기 때문에 별도의 함수가 필요.
  //}----------------------------------------------------------------------------

  //[수평이동 정보 구조]{*******************************************************************************************************
  //
  //      4Byte         1Byte           4Byte                  4Byte                    4Byte               4Byte       4Byte
  //{ <편집기index> + <'>'/'<'> + <시작행:시작위치> + <수정전:끝행:시작위치> + <수정후:끝행:시작위치> + <이동공백수> + <크기> }
  //
  //  |<---------------------------------------------<고정크기:21Byte>-------------------------------------------->|     21
  //
  //}***************************************************************************************************************************

  //[추가 가능 확인및 공간 확보]
  //{
      //[!]{---------------------------------------------------------------------
      //추가할 공간이 부족한 경우는 자동으로 가장 처음에 추가한 [되돌림묶음] 을
      //삭제하고, 공간 확보에 오류가 있는 경우는 더이상 처리하지 않고 종료한다.
      //}------------------------------------------------------------------------

      if(History_CheckAndMake() != true)
      {
        //[!]{--------------------------------------------------------------------
        //[수정내용] 이 저장할수 없을 만큼 큰 경우는 추가하지 않으며, 이전의 저장
        //내용도 전부 삭제하고 초기화 한다.
        //}-----------------------------------------------------------------------

        ide_msgbox_Form->_MsgBox
        (d_MSGBOX_info,
         "현 위치의 [수정내용] 추가에 경고가 발생하였습니다.\r\n"
         "[수정이력] 관리 공간을 넘는 크기의 문자열은 관리되지 않습니다.\r\n"
         "따라서, 현재 [수정내용] 은 [수정이력] 에 등록되지 않으며 이전의\r\n"
         "모든 [수정이력] 은 초기화됩니다."
        );

        //이 경우는 이전의 모든 [수정이력] 을 초기화 한다.
        History_Init();

        return;

      }

  //}

  //[초기화]
  //{
      //[!]{--------------------------------------------------------------
      //현재 [되돌림묶음] 위치부터 다시 저장 되어야 하므로 이 위치를 일단
      //끝 위치로 수정한다. 뒤의 [되돌림묶음] 은 버린다.
      //}-----------------------------------------------------------------

      _history.bufCount = _history.packetPtr;

  //}

  //[입력지정자 배치 위치]
  //{
      //문자열 시작 위치가 해당 위치가 된다.
      *(int *)(&(_history.buf[_history.bufCount])) = pCaretIndex;

      //이 정보는 4 Byte 크기를 갖는다.
      _history.bufCount += 4;

  //}

  //[수정 종류 기록]
  //{
      _history.buf[_history.bufCount] = pKind;

      //이 정보는 1 Byte 크기를 갖는다.
      _history.bufCount += 1;

  //}

  //[시작행:시작위치]
  //{
      //문자열 시작 위치가 해당 위치가 된다.
      *(int *)(&(_history.buf[_history.bufCount])) = pStartLineStartIndex;

      //이 정보는 4 Byte 크기를 갖는다.
      _history.bufCount += 4;

  //}

  //[수정전:끝행:시작위치]
  //{
      //문자열 시작 위치가 해당 위치가 된다.
      *(int *)(&(_history.buf[_history.bufCount])) = pEndLineStartIndex;

      //이 정보는 4 Byte 크기를 갖는다.
      _history.bufCount += 4;

  //}

  //[수정후:끝행:시작위치]
  //{
      //문자열 시작 위치가 해당 위치가 된다.
      *(int *)(&(_history.buf[_history.bufCount])) = pEndLineStartIndex_moved;

      //이 정보는 4 Byte 크기를 갖는다.
      _history.bufCount += 4;

  //}

  //[이동수]
  //{
      //문자열 시작 위치가 해당 위치가 된다.
      *(int *)(&(_history.buf[_history.bufCount])) = pMoveCount;

      //이 정보는 4 Byte 크기를 갖는다.
      _history.bufCount += 4;

  //}

  //[크기 정보 기록]
  //{
      //현재 시점까지의 [수정이력 묶음] 크기를 기록.
      //이미 <bufCount> 는 다음 저장 위치에 있으므로 +1 을 하지 않고 [되돌림묶음] 의
      //시작 위치를 빼면 [크기] 가 된다.
      *(int *)(&(_history.buf[_history.bufCount])) = _history.bufCount - _history.packetPtr;

      //이 정보는 4 Byte 크기를 갖는다.
      _history.bufCount += 4;

  //}

  //[되돌림묶음 위치 수정]
  //{
      //한개의 [되돌림묶음] 을 추가 하였으므로 다시 다음 저장 위치로 이동 시킨다.
      _history.packetPtr = _history.bufCount;

  //}

  return;

}

//------------------------------------------------------------------------------
//[되돌림/되살림 기능관련]------------------------------------------------------
//------------------------------------------------------------------------------

void __fastcall Teditor_edit_Form::History_Init(void)
{
  //[2009.05.02.토][생성!!!]{------------------
  //[되돌림/되살림] 정보 구조체를 초기화 한다.
  //}------------------------------------------

  _history.buf[0]    = 0;
  _history.bufCount  = 0;

  //처음 [명령묶음] 위치는 0 이다.
  _history.packetPtr = 0;

  //[편집기 상의 위치는 사용하지 않는 경우는 무효값인 -1 로 초기화 한다.
  _history.strStartIndex = -1;
  _history.strEndIndex   = -1;

  return;

}

bool __fastcall Teditor_edit_Form::History_CheckAndMake(void)
{
  //[2009.05.04][생성!!!]{------------------------------------------------------
  //현재 추구할 [되돌림묶음] 의 크기를 조사하여 현재 추가할수 있을만큼 공간이
  //충분한지 조사하고 공간이 부족하다면 가장 처음에 추가한 것을 삭제하여 공간을
  //늘리는 것 까지 수행한다.
  //
  //[2009.05.06.수][수정!!!]----------------------------------------------------
  //[되돌림묶음] 의 구조가 수정되었으므로 이에 따른 수정을 한다.
  //}---------------------------------------------------------------------------

  //[VAR]
  //{
      //현재 남은 공간 크기.
      int    emptySize;

      //추가할 [되돌림묶음] 크기.
      int    addPacketSize;

      //한개 [되돌림묶음] 크기.
      int    packetSize;

      //공간 확보를 위하여 삭제해야 하는 크기.
      int    deleteSize;

      char  *str;

  //}

  //남은 공간 크기 구하기.
  emptySize = d_History_Max - _history.bufCount;

  //추가하는 [되돌림묶음] 크기 구하기.
  addPacketSize = _history.strEndIndex - _history.strStartIndex + 11;

  if(addPacketSize > emptySize)
  {
    //[!]{-------------------------------------------------------------------------
    //이 경우는 추가하기에 공간이 부족하므로 가장 처음에 추가된 것을 삭제하여
    //추가로 공간을 확보해 주어야 한다.
    //이는 가장 처음의 [되돌림묶음] 의 크기를 차례로 구해서 합산하여 충분한 공간이
    //만들어 진다면 이 크기만큼 삭제해주면 된다.
    //}----------------------------------------------------------------------------

    for(deleteSize = 0; deleteSize < _history.bufCount; )
    {
      //[되돌림묶음 크기 얻기]
      //{
          //[문자열 위치 얻기]{------------------
          str = &(_history.buf[deleteSize + 6]);
          //}------------------------------------

          //현재 위치의 [되돌리묶음 크기를 구한다.
          packetSize = 11 + STR_Length(str);

          //삭제할 크기 수정.
          deleteSize += packetSize;

      //}

      //[삭제] 할 공간이 [필요] 공간보다 큰경우는 더이상 공간을 만들지 않는다.
      if(deleteSize > addPacketSize) goto PACKET_DELETE;

    }

    //여기로 온것은 공간 확보에 문제가 발생한 것이다.
    return(false);


    PACKET_DELETE:
    //{
        //[!]{---------------------------------------------------------------------
        //확보할 공간 만큼 해당하는 [되돌림묶음] 을 삭제한다.
        //이미 크기는 deleteSize 에 들어 있으므로 memmove() 를 사용하여 [끌어덮는]
        //방식으로 고속 처리한다.
        //}------------------------------------------------------------------------

        memmove(&(_history.buf[0]), &(_history.buf[deleteSize]), _history.bufCount - deleteSize);

        //[정보수정]
        //{
            //삭제한 크기만큼 위치를 수정한다.
            _history.packetPtr -= deleteSize;
            _history.bufCount  -= deleteSize;

        //}

    //}


    return(true);

  }
  else
  {
    //이 경우는 이미 공간이 충분하므로 그냥 추가하면 된다.

  }

  return(true);

}

void __fastcall Teditor_edit_Form::History_Add(//추가('+')인지 삭제('-')인지 구분한다.
                                               char  pChangeKind,
                                               //[2009.05.06.수][추가!!!]
                                               //<c:문자>, <s:문자열> 인지 구분한다.
                                               char  pCharString)
{
  //[2009.05.02.토][생성!!!]{--------------------------------------------------------
  //기본 정보를 전달 받아서 [되돌림묶음] 을 만들고 이를 [저장소] 에 추가한다.
  //단, [추가] 로 수정되는 경우와 [삭제] 로 수정되는 경우가 있으나 여기서는 정보를
  //정리하여 저장해 주기만 하면된다.
  //
  //[2009.05.03.일][중요수정!!!]-----------------------------------------------------
  //_history.strStartIndex, _history.strEndIndex 에 이미 정보가 들어 있으므로
  //이 정보를 사용하여 처리한다.
  //단, 1개의 문자라도 선택된 경우는 "_history.strStartIndex < _history.strEndIndex"
  //이어야 한다. 선택은 반드시 영역 다음 문자 위치 까지가 영역이 된다.
  //"AB" 에서 "A" 를 [선택영역] 으로 지정하는 경우는 "B" 문자 위치가 끝위치가 된다.
  //[문자열] 길이 계산시 이 점 주의하여 처리해야 한다.
  //
  //[2009.05.06.수][수정!!!]---------------------------------------------------------
  //[되돌림묶음] 의 구조가 수정되었으므로 이에 따른 수정을 해준다.
  //
  //[2009.06.03.수][중요수정!!!]-----------------------------------------------------
  //[수정내용] 이 용량을 초과 하는 경우는 추가할수 없으므로 저장 순서를 고려하여
  //이전의 모든 저장 내용도 같이 초기화 한다.
  //}--------------------------------------------------------------------------------

  //[<되돌림묶음> 구조]{------------------------------------------------
  //      4Byte         1Byte       1Byte        XByte         4Byte
  //{ <편집기index> + <'+'/'-'> + <'c'/'s'> +<문자열 + '\0'> + <크기> }
  //  |<---------------------<크기>----------------------->|
  //}-------------------------------------------------------------------


  //[추가 가능 확인및 공간 확보]
  //{
      //[2009.05.04.월][추가!!!]
      //추가할 공간이 부족한 경우는 자동으로 가장 처음에 추가한 [되돌림묶음] 을
      //삭제하고, 공간 확보에 오류가 있는 경우는 더이상 처리하지 않고 종료한다.
      if(History_CheckAndMake() != true)
      {
        //[2009.06.03.수][수정!!!]{---------------------------------------------------------
        //이 경우는 너무 많은 문자열의 붙여넣기 등으로 [줄이동] 되는 경우 사라져
        //보이지 않게 된다. 따라서 아래의 일반 [알림글] 을 보여주는 방식으로 금일 교체한다.
        //추가로, [수정내용] 이 저장할수 없을 만큼 큰 경우는 추가하지 않으며, 이전의 저장
        //내용도 전부 삭제하고 초기화 한다.
        //}---------------------------------------------------------------------------------

        /*
        ide_hint_Form->_ShowHint_EditDebugPanel
        (ide_editor_Form->Left + d_gutter_width - 1,
         ide_editor_Form->Top + editor_top_Form->Height + _caret_y,
         "현 위치의 [수정내용] 추가에 오류가 발생하였습니다.\r\n"
         "[수정이력] 관리 공간을 넘는 크기의 문자열은 관리되지 않습니다.\r\n"
         "따라서, 현재 수정 내용은 [수정이력] 에 등록되지 않습니다."
        );
        */

        ide_msgbox_Form->_MsgBox
        (d_MSGBOX_info,
         "현 위치의 [수정내용] 추가에 경고가 발생하였습니다.\r\n"
         "[수정이력] 관리 공간을 넘는 크기의 문자열은 관리되지 않습니다.\r\n"
         "따라서, 현재 [수정내용] 은 [수정이력] 에 등록되지 않으며 이전의\r\n"
         "모든 [수정이력] 은 초기화됩니다."
        );

        //이 경우는 이전의 모든 [수정이력] 을 초기화 한다.
        History_Init();

        return;

      }

  //}


  //[초기화]
  //{
      //현재 [되돌림묶음] 위치부터 다시 저장 되어야 하므로 이 위치를 일단
      //끝 위치로 수정한다. 뒤의 [되돌림묶음] 은 버린다.
      _history.bufCount = _history.packetPtr;

  //}

  //[편집기상 위치 기록]
  //{
      //문자열 시작 위치가 해당 위치가 된다.
      *(int *)(&(_history.buf[_history.bufCount])) = _history.strStartIndex;

      //이 정보는 4 Byte 크기를 갖는다.
      _history.bufCount += 4;

  //}

  //[수정 종류 기록]
  //{
      _history.buf[_history.bufCount] = pChangeKind;

      //이 정보는 1 Byte 크기를 갖는다.
      _history.bufCount += 1;

  //}

  //[문자/문자열 구분 기록]
  //{
      //[2009.05.06.수][추가!!!]
      _history.buf[_history.bufCount] = pCharString;

      //이 정보는 1 Byte 크기를 갖는다.
      _history.bufCount += 1;

  //}

  //[문자열 기록]
  //{
      //고속 처리를 위하여 memmove() 를 사용한다.
      memmove(&(_history.buf[_history.bufCount]),
              &(_editbuf[_history.strStartIndex]),
              _history.strEndIndex - _history.strStartIndex);

      //문자열 길이 만큼 증가 시킨다.
      _history.bufCount += (_history.strEndIndex - _history.strStartIndex);

      //문자열이므로 끝에 '\0' 을 추가한다.
      _history.buf[_history.bufCount] = '\0';

      //이 정보는 1 Byte 크기를 갖는다.
      _history.bufCount += 1;

  //}

  //[크기 정보 기록]
  //{
      //처음부터 문자열 '\0' 까지를 포함된 [크기] 를 구해서 저장한다.
      //이미 <bufCount> 는 다음 저장 위치에 있으므로 +1 을 하지 않고 [되돌림묶음] 의
      //시작 위치를 빼면 [크기] 가 된다.
      *(int *)(&(_history.buf[_history.bufCount])) = _history.bufCount - _history.packetPtr;

      //이 정보는 4 Byte 크기를 갖는다.
      _history.bufCount += 4;

  //}

  //[되돌림묶음 위치 수정]
  //{
      //한개의 [되돌림묶음] 을 추가 하였으므로 다시 다음 저장 위치로 이동 시킨다.
      _history.packetPtr = _history.bufCount;

  //}

}

void __fastcall Teditor_edit_Form::History_UnDo(void)
{
  //[2009.05.02.토][생성!!!]{-------------------------------------------------
  //[되돌림묶음 저장소] 에서 현재 [되돌림] 위치 이전의 [되돌림묶음] 의 정보를
  //참고하여 한개를 [되돌림] 한다(현재 위치가 아니라 이전것을 사용해야 한다).
  //현재 <packetPtr> 의 위치의 [되돌림묶음] 이 해당되며 [추가/삭제] 된 상태를
  //참고하여처리한다.
  //
  //[2012.02.05.일][중요수정!!!]----------------------------------------------
  //[수평이동] 관련 처리를 추가한다.
  //[두번째 정보] 인 [1 바이트] 가 '>', '<' 인 경우가 해당된다.
  //
  //[수평이동] 은 [첫번째/두번째] 정보를 제외한 다음 정보부터는 [기본편집] 과
  //완전히 다르므로 별도로 [수정이력] 정보에 접근해야 한다.
  //
  //[2012.06.01.금][수정!!!]--------------------------------------------------
  //[2012.06.11.월][수정!!!]--------------------------------------------------
  //}-------------------------------------------------------------------------

  //[VAR]
  //{
      int    editIndex;
      char   changeKind;
      char  *str;

      //[2009.05.06.수][추가!!!]
      char   char_string;
      short  code;

      //[수평이동 처리용]
      //{
          //[2012.02.06.월][추가!!!]
          int  sLineStartIndex;
          int  eLineStartIndex;
          //처리후 변화된 [끝행:시작위치].
          int  eLineStartIndex_moved;
          int  moveCount;

      //}

  //}

  //[처리할것이 있나?]
  //{
      //이미 바닥위치라면 더이상 되돌릴 것이 없으므로 아무 처리도 하지 않는다.
      if(_history.packetPtr <= 0) return;

  //}

  //[<되돌림묶음> 위치 구하기]
  //{
      _history.packetPtr = _history.packetPtr -
                         //|<--------------------[크기]---------------------->|
                           ((*(int *)(&(_history.buf[_history.packetPtr - 4]))) +
                            //[크기] 정보 자체 크기.
                            4);

  //}

  //[정보추출]
  //{
      //[편집기] 상의 위치 정보를 얻는다.
      editIndex = (*(int *)(&(_history.buf[_history.packetPtr])));

      //[추가/삭제] 인지 [수정종류] 를 얻는다.
      changeKind = _history.buf[_history.packetPtr + 4];

      //[<기본편집/수평이동> 구분]
      //{
          //[2012.02.05.일][중요추가!!!]{-----------------------------------------
          //여기서 바로 [수평이동] 정보인지 검사한다.
          //이는 [첫번째/두번째] 정보까지는 동일하고 다음부터는 [수정이력] 정보가
          //서로 다르기 때문이다.
          //[두번째:종류] 정보로 쉽게 구분할수 있다.
          //}---------------------------------------------------------------------

          //[수평이동] 인 경우는 바로 해당 처리부로 이동.
          if((changeKind == '>') || (changeKind == '<')) goto lbMoveRL;

          //[수평이동] 이 아닌 경우는 [일반편집] 처리로 계속 진행.

      //}

      //[2009.05.06.수][추가!!!]{-------------------------
      //[문자/문자열] 인지 종류를 얻는다.
      char_string = _history.buf[_history.packetPtr + 5];
      //}-------------------------------------------------

      //문자열 위치 얻기.
      str = &(_history.buf[_history.packetPtr + 6]);

  //}


  //[함수 사용 제어]
  //{
      //[2012.06.01.금][추가!!!]{-------------------------------------------
      //<Tinfo_tree_Form::_AutoHide_WordBound()> 함수 처리 허용 제어.
      //이 함수 마지막에 한번만 처리하기 위하여 내부에서는 처리하지 않는다.
      //}-------------------------------------------------------------------

      info_tree_Form->_sw_AutoHide_WordBound = false;

  //}


  //[종류에 따른 처리]
  //{
      //[추가/삭제] 로 변경된 경우를 구분하여 처리해야 한다.
      if     (changeKind == '+')
      {
        //[!]{-------------------------------------------------------------------
        //[추가] 로 수정된 경우이므로 [편집기] 상의 지정 위치에서 이 [문자열] 의
        //길이만큼 [삭제] 해 주어야 한다.
        //
        //1) [입력지정자] 위치를 지정위치로 이동.
        //2) 이위치에서 [문자열] 길이만큼 [삭제] 한다.
        //   이는 (가)블록으로 지정 -> (나)잘라내기 와 같은 과정이다.
        //
        //[2009.05.06.수][수정!!!]-----------------------------------------------
        //[문자/문자열] 을 구분하여 처리한다.
        //}----------------------------------------------------------------------

        if     (char_string == 'c') //문자인경우.
        {
          //[!]{-----------------------------------------------------------------------
          //[한글/영문/CRLF] 이 해당된다.
          //이 경우는 간단하게 위치를 지정후 KEY_Delete() 로 처리한다.
          //이는 계속 전체가 다시 그려지는 경우 속도가 느려지는 것을 막기 위한 것이다.
          //}--------------------------------------------------------------------------

          //[입력지정자] 를 지정 위치로 이동 시킨다.
          History_SetCaretPos(editIndex, true);

          //[문자] 를 삭제한다.
          //[선택영역] 이 없으므로 History_SelectDelete() 함수를 사용해서는 안된다.
          _KEY_Delete(false);

        }
        else if(char_string == 's') //문자열인 경우.
        {
          //[2009.05.06.수][중요추가!!!]{----------------------------------------------
          //같은 함수로 먼저 [입력지정자] 위치를 설정해 놓는다.
          //이는 [선택영역] 이 설정된 상태로 다시 그려지는 경우는 [선택영역] 이
          //보이게 되므로 다른 과정과 다르게 된다. 따라서 보기 좋게 먼저 위치를
          //설정하고 이 함수를 다시 호출하여 [선택영역] 을 설정하도록한다.
          //이 경우는 이미 [입력지정자] 가 보이는 위치에 있으므로 다시 그려지지 않아서
          //[선택영역] 이 보이지 않게 된다.
          History_SetCaretPos(editIndex, true);
          //}--------------------------------------------------------------------------

          //[입력지정자] 위치로 이동과 [문자열 선택] 을 같이 수행한다.
          History_SelectX(editIndex, editIndex + STR_Length(str), true, NULL, false,
                          //보이는 영역에만 있으면 된다.
                          false, false);

          //[문자열] 을 삭제한다.
          History_SelectDelete();

        }

      }
      else if(changeKind == '-')
      {
        //[!]{------------------------------------------------------------------------------
        //[삭제] 로 수정된 경우이므로 [편집기] 상의 지정 위치에 [문자열 을 [붙여넣기] 한다.
        //
        //1) [입력지정자] 위치를 지정위치로 이동.
        //2) 이위치에서 [문자열] 을 붙여넣기 한다.
        //   이는 [붙여넣기] 와 기능이 같다.
        //
        //[2009.05.06.수][수정!!!]----------------------------------------------------------
        //[문자/문자열] 인 경우를 구분하여 처리한다.
        //}---------------------------------------------------------------------------------

        if     (char_string == 'c') //문자인경우.
        {
          //[!]{-----------------------------------------------------------------------
          //[한글/영문] : _CARET_MOONJA_Insert(<ODE>)  를 사용하여 직접 문자를 입력한다.
          //[CRLF     ] : _KEY_Enter() 함수로 직접 처리.
          //}--------------------------------------------------------------------------

          //실제 [선택영역] 은 없지만 [입력지정자] 위치 이동을 위하여 사용한다.
          History_SetCaretPos(editIndex, true);

          if((str[0] == 0x0d) && (str[1] == 0x0a))
          {
            //추가할 문자가 <CRLF> 인 경우는 직접 <키> 입력을 수행한다.
            _KEY_Enter(false);

          }
          else
          {
            //[한글/영문] 인 경우를 구분하여 먼저 <CODE> 를 추출한다.
            if(str[1] == '\0')
            {
              //[영문] 의 경우.
              code = str[0];

            }
            else
            {
              //[한글] 의 경우.
              code = (((str[0] << 8) & 0xff00)) | (str[1] & 0x00ff);

            }

            //직접 입력한다([수정이력] 은 반영하지 않는다).
            _CARET_MOONJA_Insert(code, false);

          }

        }
        else if(char_string == 's') //문자열인 경우.
        {
          //실제 [선택영역] 은 없지만 [입력지정자] 위치 이동을 위하여 사용한다.
          History_SetCaretPos(editIndex, true);

          //[문자열] 을 삭제한다.
          History_Insert(str, true);

        }

      }

  //}


  //[함수 사용 제어]
  //{
      //[2012.06.01.금][추가!!!]{-------------------------------------
      //<Tinfo_tree_Form::_AutoHide_WordBound()> 함수 처리 허용 제어.
      //함수 사용을 허가한다.
      //}-------------------------------------------------------------

      info_tree_Form->_sw_AutoHide_WordBound = true;

  //}


  //[실시간 선언 정보판 관련]
  //{
      //[단어 구간 정보 추출]
      //{
          //[2012.05.24.목][추가!!!]{---------------------------------------------
          //실시간으로 [입력지정자] 가 위치한 [단어] 의 [시작/끝:위치] 를 관리.
          //
          //[2012.06.01.금][설명!!!]----------------------------------------------
          //<_EDITBUF_LINE_Out()> 에서 [실시간 선언 정보판:대상단어] 를 지정할때
          //<_wordStartIndex/_wordEndIndex> 정보를 사용하므로 항상 수집해 놓는다.
          //위에서 금지해 놓았기 때문에 여기서 한번은 반드시 처리해야 한다.
          //}---------------------------------------------------------------------

          STR_Get_WordBound(_editbuf, _filesize, _caretindex,
                            &_wordStartIndex,
                            &_wordEndIndex);

      //}

      //[실시간 선언 정보판 감추기]
      //{
          //[2012.05.24.목][추가!!!]{----------------------------
          //[실시간 선언 정보판] 이 보이는 경우만 처리하고
          //처리후 반드시 [단어지정] 을 위하여 [입력지정자] 가
          //위치한행만 다시 그린다.
          //
          //더불어, <info_tree_Form->_AutoHide_WordBound()> 에서
          //기존 [단어 구간] 을 벗어난 경우는 자동으로 감춰진다.
          //}----------------------------------------------------

          if(info_tree_Form != NULL)
          {
            if((info_tree_Form->Visible == true) &&
               //[2012.06.01.금][추가!!!]
               //<_AutoHide_WordBound()> 함수 사용 허가상태만 처리.
               (info_tree_Form->_sw_AutoHide_WordBound == true))
            {
              //현재 [단어 구간 정보] 전달.
              info_tree_Form->_AutoHide_WordBound(_wordStartIndex, _wordEndIndex);

              //현재 [입력지정자] 가 위치한 행만 다시 그린다.
              _EditBuf_LineText(_row, false);

            }

          }

      //}
      
  //}

  //여기서 [기본편집] 처리를 종료한다.
  return;


  //***************************
  lbMoveRL: //[수평이동] 처리.
  //***************************
  //{
      //[2012.02.05.일][추가!!!]{----------------------------------------------
      //[수평이동] 관련 [수정이력] 처리.
      //
      //이미 이 함수 첫 부분에서 추출한 정보는 [첫번째/두번째] 정보 뿐이다.
      //이는 [일반편집] 과 공통적인 부분이고, 나머지는 개별 추출하여 사용한다.
      //}----------------------------------------------------------------------

      //[수평이동 정보 구조]{*******************************************************************************************************
      //
      //      4Byte          1Byte          4Byte                  4Byte                    4Byte               4Byte       4Byte
      //{ <편집기index> + <'>'/'<'> + <시작행:시작위치> + <수정전:끝행:시작위치> + <수정후:끝행:시작위치> + <이동공백수> + <크기> }
      //
      //  |<---------------------------------------------<고정크기:21Byte>-------------------------------------------->|     21
      //
      //}***************************************************************************************************************************

      //[정보얻기]
      //{
          //[!]{------------------------------------------------------------------------------------------------------
          //[시작행 시작위치], [수정전 끝행 시작위치], [수정후 끝행 시작위치], [이동공백수] 각 <4바이트> 정보를 추출.
          //}---------------------------------------------------------------------------------------------------------

          sLineStartIndex       = (*(int *)(&(_history.buf[_history.packetPtr + 4 + 1])));
          eLineStartIndex       = (*(int *)(&(_history.buf[_history.packetPtr + 4 + 1 + 4])));
          eLineStartIndex_moved = (*(int *)(&(_history.buf[_history.packetPtr + 4 + 1 + 4 + 4])));
          moveCount             = (*(int *)(&(_history.buf[_history.packetPtr + 4 + 1 + 4 + 4 + 4])));

      //}

      //[종류에 따른 처리]
      //{
          //[참고!!!]{-----------------------------------------------------------------------
          //[수평이동:수정이력] 저장시 [입력지정자위치] 를 <sLineStartIndex> 와 같은 위치로
          //저장하였으므로 <sLineStartIndex> 를 사용해도 무관하지만, 개념적으로 [입력지정자]
          //위치와 같기 때문에 [입렭지정자] 위치인 <editIndex> 값을 그냥 사용한다.
          //}--------------------------------------------------------------------------------

          //[추가/삭제] 로 변경된 경우를 구분하여 처리해야 한다.
          if     (changeKind == '>')
          {
            //[수평이동:오른쪽] 의 [수정이력] 이므로 [수평이동:왼쪽] 으로 처리.
            History_MoveRL_Left(editIndex,
                                sLineStartIndex,
                                //변화된 위치를 시작값으로 설정.
                                eLineStartIndex_moved,
                                moveCount);

          }
          else if(changeKind == '<')
          {
            //[수평이동:왼쪽] 의 [수정이력] 이므로 [수평이동:오른쪽] 으로 처리.
            History_MoveRL_Right(editIndex,
                                 sLineStartIndex,
                                 //변화된 위치를 시작값으로 설정.
                                 eLineStartIndex_moved,
                                 moveCount);

          }

      //}

      return;

  //}

}

void __fastcall Teditor_edit_Form::History_ReDo(void)
{
  //[2009.05.02.토][생성!!!]{-----------------------------------------------------
  //[되돌림묶음 저장소] 에서 현재 [되돌림] 위치의 [되돌림묶음] 의 정보를 참고하여
  //한개를 [되살림] 한다.
  //현재 <packetPtr> 의 위치의 [되돌림묶음] 이 해당되며 [추가/삭제] 된 상태를
  //참고하여처리한다.
  //
  //[2012.02.06.월][중요수정!!!]--------------------------------------------------
  //[수평이동] 관련 처리를 추가한다.
  //[두번째 정보] 인 [1 바이트] 가 '>', '<' 인 경우가 해당된다.
  //
  //[수평이동] 은 [첫번째/두번째] 정보를 제외한 다음 정보부터는 [기본편집] 과
  //완전히 다르므로 별도로 [수정이력] 정보에 접근해야 한다.
  //
  //[2012.06.01.금][수정!!!]------------------------------------------------------
  //[2012.06.11.월][수정!!!]------------------------------------------------------
  //}-----------------------------------------------------------------------------

  //[VAR]
  //{
      int    editIndex;
      char   changeKind;
      char  *str;

      //[2009.05.06.수][추가!!!]
      char   char_string;
      short  code;

      //[수평이동 처리용]
      //{
          //[2012.02.06.월][추가!!!]
          int  sLineStartIndex;
          int  eLineStartIndex;
          //처리후 변화된 [끝행:시작위치].
          int  eLineStartIndex_moved;
          int  moveCount;

      //}

  //}

  //[확인]
  //{
      //이미 끝위치라면 더이상 되살릴 것이 없으므로 아무 처리도 하지 않는다.
      if(_history.packetPtr >= _history.bufCount) return;

  //}

  //[<되살림묶음> 위치 구하기]
  //{
      //현재 위치가 지금 처리할 [되살림묶음] 위치가 된다.

  //}

  //[정보추출]
  //{
      //[편집기] 상의 위치 정보를 얻는다.
      editIndex = (*(int *)(&(_history.buf[_history.packetPtr])));

      //[추가/삭제] 인지 [수정종류] 를 얻는다.
      changeKind = _history.buf[_history.packetPtr + 4];

      //[<기본편집/수평이동> 구분]
      //{
          //[2012.02.06.월][중요추가!!!]{-----------------------------------------
          //여기서 바로 [수평이동] 정보인지 검사한다.
          //이는 [첫번째/두번째] 정보까지는 동일하고 다음부터는 [수정이력] 정보가
          //서로 다르기 때문이다.
          //[두번째:종류] 정보로 쉽게 구분할수 있다.
          //}---------------------------------------------------------------------

          //[수평이동] 인 경우는 바로 해당 처리부로 이동.
          if((changeKind == '>') || (changeKind == '<')) goto lbMoveRL;

          //[수평이동] 이 아닌 경우는 [일반편집] 처리로 계속 진행.

      //}

      //[2009.05.06.수][추가!!!]{-------------------------
      //[문자/문자열] 인지 종류를 얻는다.
      char_string = _history.buf[_history.packetPtr + 5];
      //}-------------------------------------------------

      //문자열 위치 얻기.
      str = &(_history.buf[_history.packetPtr + 6]);

  //}


  //[함수 사용 제어]
  //{
      //[2012.06.01.금][추가!!!]{-------------------------------------------
      //<Tinfo_tree_Form::_AutoHide_WordBound()> 함수 처리 허용 제어.
      //이 함수 마지막에 한번만 처리하기 위하여 내부에서는 처리하지 않는다.
      //}-------------------------------------------------------------------

      info_tree_Form->_sw_AutoHide_WordBound = false;

  //}


  //[종류에 따른 처리]
  //{
      //[추가/삭제] 로 변경된 경우를 구분하여 처리해야 한다.
      if     (changeKind  == '+')
      {
        //[!]{------------------------------------------------------------------------------
        //[추가] 로 수정된 경우이므로 [편집기] 상의 지정 위치에 [문자열 을 [붙여넣기] 한다.
        //
        //1) [입력지정자] 위치를 지정위치로 이동.
        //2) 이위치에서 [문자열] 을 붙여넣기 한다.
        //   이는 [붙여넣기] 와 기능이 같다.
        //
        //[2009.05.06.수][수정!!!]----------------------------------------------------------
        //[문자/문자열] 인 경우를 구분하여 처리한다.
        //}---------------------------------------------------------------------------------


        if     (char_string == 'c') //문자인경우.
        {
          //[!]{-----------------------------------------------------------------------
          //[한글/영문] : _CARET_MOONJA_Insert(<ODE>)  를 사용하여 직접 문자를 입력한다.
          //[CRLF     ] : _KEY_Enter() 함수로 직접 처리.
          //}--------------------------------------------------------------------------

          //실제 [선택영역] 은 없지만 [입력지정자] 위치 이동을 위하여 사용한다.
          History_SetCaretPos(editIndex, true);

          if((str[0] == 0x0d) && (str[1] == 0x0a))
          {
            //추가할 문자가 <CRLF> 인 경우는 직접 <키> 입력을 수행한다.
            _KEY_Enter(false);

          }
          else
          {
            //[한글/영문] 인 경우를 구분하여 먼저 <CODE> 를 추출한다.
            if(str[1] == '\0')
            {
              //[영문] 의 경우.
              code = str[0];

            }
            else
            {
              //[한글] 의 경우.
              code = (((str[0] << 8) & 0xff00)) | (str[1] & 0x00ff);

            }

            //직접 입력한다([수정이력] 은 반영하지 않는다).
            _CARET_MOONJA_Insert(code, false);

          }

        }
        else if(char_string == 's') //문자열인 경우.
        {
          //실제 [선택영역] 은 없지만 [입력지정자] 위치 이동을 위하여 사용한다.
          History_SetCaretPos(editIndex, true);

          //[문자열] 을 추가한다.
          History_Insert(str, true);

        }

      }
      else if(changeKind  == '-')
      {
        //[!]{-------------------------------------------------------------------
        //[삭제] 로 수정된 경우이므로 [편집기] 상의 지정 위치에서 이 [문자열] 의
        //길이만큼 [삭제] 해 주어야 한다.
        //
        //1) [입력지정자] 위치를 지정위치로 이동.
        //2) 이위치에서 [문자열] 길이만큼 [삭제] 한다.
        //   이는 (가)블록으로 지정 -> (나)잘라내기 와 같은 과정이다.
        //
        //[2009.05.06.수][수정!!!]-----------------------------------------------
        //[문자/문자열] 을 구분하여 처리한다.
        //}----------------------------------------------------------------------

        if     (char_string == 'c') //문자인경우.
        {
          //[!]{-----------------------------------------------------------------------
          //[한글/영문/CRLF] 이 해당된다.
          //이 경우는 간단하게 위치를 지정후 KEY_Delete() 로 처리한다.
          //이는 계속 전체가 다시 그려지는 경우 속도가 느려지는 것을 막기 위한 것이다.
          //}--------------------------------------------------------------------------

          //[입력지정자] 를 지정 위치로 이동 시킨다.
          History_SetCaretPos(editIndex, true);

          //[문자] 를 삭제한다.
          //[선택영역] 이 없으므로 History_SelectDelete() 함수를 사용해서는 안된다.
          _KEY_Delete(false);

        }
        else if(char_string == 's') //문자열인 경우.
        {
          //[2009.05.06.수][중요추가!!!]{----------------------------------------------
          //같은 함수로 먼저 [입력지정자] 위치를 설정해 놓는다.
          //이는 [선택영역] 이 설정된 상태로 다시 그려지는 경우는 [선택영역] 이
          //보이게 되므로 다른 과정과 다르게 된다. 따라서 보기 좋게 먼저 위치를
          //설정하고 이 함수를 다시 호출하여 [선택영역] 을 설정하도록한다.
          //이 경우는 이미 [입력지정자] 가 보이는 위치에 있으므로 다시 그려지지 않아서
          //[선택영역] 이 보이지 않게 된다.
          History_SetCaretPos(editIndex, true);
          //}--------------------------------------------------------------------------

          //[입력지정자] 위치로 이동과 [문자열 선택] 을 같이 수행한다.
          History_SelectX(editIndex, editIndex + STR_Length(str), true, NULL, false,
                          //보이는 영역에만 있으면 된다.
                          false, false);

          //[문자열] 을 삭제한다.
          History_SelectDelete();

        }

      }

  //}

  //[<되살림묶음> 위치 이동]
  //{
      //[2009.05.04.월][추가!!!]{--------------------------------------------------
      //한개를 [되살림] 했으므로 다시 다음 [되살림묶음] 이 있는 위치로 이동시킨다.
      //}--------------------------------------------------------------------------

      _history.packetPtr += (//[편집기] 상 위치정보 크기.
                             4 +
                             //수정종류 크기.
                             1 +
                             //문자/문자열 구분.
                             1 +
                             //문자열길이('\0' 까지 포함해야 한다)
                             STR_Length(str) + 1 +
                             //묶음크기 정보.
                             4);

  //}


  //[함수 사용 제어]
  //{
      //[2012.06.01.금][추가!!!]{-------------------------------------
      //<Tinfo_tree_Form::_AutoHide_WordBound()> 함수 처리 허용 제어.
      //함수 사용을 허가한다.
      //}-------------------------------------------------------------

      info_tree_Form->_sw_AutoHide_WordBound = true;

  //}

  //[실시간 선언 정보판 관련]
  //{
      //[단어 구간 정보 추출]
      //{
          //[2012.05.24.목][추가!!!]{---------------------------------------------
          //실시간으로 [입력지정자] 가 위치한 [단어] 의 [시작/끝:위치] 를 관리.
          //
          //[2012.06.01.금][설명!!!]----------------------------------------------
          //<_EDITBUF_LINE_Out()> 에서 [실시간 선언 정보판:대상단어] 를 지정할때
          //<_wordStartIndex/_wordEndIndex> 정보를 사용하므로 항상 수집해 놓는다.
          //위에서 금지해 놓았기 때문에 여기서 한번은 반드시 처리해야 한다.
          //}---------------------------------------------------------------------

          STR_Get_WordBound(_editbuf, _filesize, _caretindex,
                            &_wordStartIndex,
                            &_wordEndIndex);

      //}

      //[실시간 선언 정보판 감추기]
      //{
          //[2012.05.24.목][추가!!!]{----------------------------
          //[실시간 선언 정보판] 이 보이는 경우만 처리하고
          //처리후 반드시 [단어지정] 을 위하여 [입력지정자] 가
          //위치한행만 다시 그린다.
          //
          //더불어, <info_tree_Form->_AutoHide_WordBound()> 에서
          //기존 [단어 구간] 을 벗어난 경우는 자동으로 감춰진다.
          //}----------------------------------------------------

          if(info_tree_Form != NULL)
          {
            if((info_tree_Form->Visible == true) &&
               //[2012.06.01.금][추가!!!]
               //<_AutoHide_WordBound()> 함수 사용 허가상태만 처리.
               (info_tree_Form->_sw_AutoHide_WordBound == true))
            {
              //현재 [단어 구간 정보] 전달.
              info_tree_Form->_AutoHide_WordBound(_wordStartIndex, _wordEndIndex);

              //현재 [입력지정자] 가 위치한 행만 다시 그린다.
              _EditBuf_LineText(_row, false);

            }

          }

      //}

  //}

  //여기서 [기본편집] 처리를 종료한다.
  return;


  //***************************
  lbMoveRL: //[수평이동] 처리.
  //***************************
  //{
      //[2012.02.05.일][추가!!!]{----------------------------------------------
      //[수평이동] 관련 [수정이력] 처리.
      //
      //이미 이 함수 첫 부분에서 추출한 정보는 [첫번째/두번째] 정보 뿐이다.
      //이는 [일반편집] 과 공통적인 부분이고, 나머지는 개별 추출하여 사용한다.
      //}----------------------------------------------------------------------

      //[수평이동 정보 구조]{*******************************************************************************************************
      //
      //      4Byte          1Byte          4Byte                  4Byte                    4Byte               4Byte       4Byte
      //{ <편집기index> + <'>'/'<'> + <시작행:시작위치> + <수정전:끝행:시작위치> + <수정후:끝행:시작위치> + <이동공백수> + <크기> }
      //
      //  |<---------------------------------------------<고정크기:21Byte>-------------------------------------------->|     21
      //
      //}***************************************************************************************************************************

      //[정보얻기]
      //{
          //[!]{------------------------------------------------------------------------------------------------------
          //[시작행 시작위치], [수정전 끝행 시작위치], [수정후 끝행 시작위치], [이동공백수] 각 <4바이트> 정보를 추출.
          //}---------------------------------------------------------------------------------------------------------

          sLineStartIndex       = (*(int *)(&(_history.buf[_history.packetPtr + 4 + 1])));
          eLineStartIndex       = (*(int *)(&(_history.buf[_history.packetPtr + 4 + 1 + 4])));
          eLineStartIndex_moved = (*(int *)(&(_history.buf[_history.packetPtr + 4 + 1 + 4 + 4])));
          moveCount             = (*(int *)(&(_history.buf[_history.packetPtr + 4 + 1 + 4 + 4 + 4])));

      //}

      //[종류에 따른 처리]
      //{
          //[참고!!!]{-----------------------------------------------------------------------
          //[수평이동:수정이력] 저장시 [입력지정자위치] 를 <sLineStartIndex> 와 같은 위치로
          //저장하였으므로 <sLineStartIndex> 를 사용해도 무관하지만, 개념적으로 [입력지정자]
          //위치와 같기 때문에 [입렭지정자] 위치인 <editIndex> 값을 그냥 사용한다.
          //}--------------------------------------------------------------------------------

          //[추가/삭제] 로 변경된 경우를 구분하여 처리해야 한다.
          if     (changeKind == '>')
          {
            //[수평이동:오른쪽] 의 [되살리기] 이므로 [수평이동:오른쪽] 으로 다시 처리.
            History_MoveRL_Right(editIndex,
                                 sLineStartIndex,
                                 //[되살리기] 이므로 처음 처리시의 [변화전위치] 를 사용.
                                 eLineStartIndex,
                                 moveCount);

          }
          else if(changeKind == '<')
          {
            //[수평이동:왼쪽] 의 [되살리기] 이므로 [수평이동:왼쪽] 으로 다시 처리.
            History_MoveRL_Left(editIndex,
                                sLineStartIndex,
                                //[되살리기] 이므로 처음 처리시의 [변화전위치] 를 사용.
                                eLineStartIndex,
                                moveCount);

          }

      //}

      //[<되살림묶음> 위치 이동]
      //{
          //[!]{-----------------------------------------------------------------------
          //한개를 [되살림] 했으므로 다시 다음 [되살림묶음] 이 있는 위치로 이동시킨다.
          //
          //[주의!!!]------------------------------------------------------------------
          //[일반편집] 과 [정보] 가 다르므로 [수평이동] 에 맞게 처리.
          //}--------------------------------------------------------------------------

          //[수평이동 정보 구조]{*******************************************************************************************************
          //
          //      4Byte          1Byte          4Byte                  4Byte                    4Byte               4Byte       4Byte
          //{ <편집기index> + <'>'/'<'> + <시작행:시작위치> + <수정전:끝행:시작위치> + <수정후:끝행:시작위치> + <이동공백수> + <크기> }
          //
          //  |<---------------------------------------------<고정크기:21Byte>-------------------------------------------->|     21
          //
          //}***************************************************************************************************************************

          _history.packetPtr += (//[편집기] 상 위치정보 크기.
                                 4 +
                                 //<수정종류>
                                 1 +
                                 //<시작행:시작위치>
                                 4 +
                                 //<수정전:끝행:시작위치>
                                 4 +
                                 //<수정전:끝행:시작위치>
                                 4 +
                                 //<이동공백수>
                                 4 +
                                 //<크기>
                                 4);

      //}

      return;

  //}

}

void __fastcall Teditor_edit_Form::History_SetCaretPos(//[입력지정자] 위치.
                                                       int    pCaretIndex,
                                                       //[입력지정자] 를 항상 보이는 위치에 두기:true.
                                                       bool   pCaretView)
{
  //[2009.02.17.화][생성!!!]{------------------------------------------
  //[되돌리기/되살리기] 시에 [입력지정자] 를 지정 위치에 위치시켜준다.
  //
  //[2012.06.13.수][중요수정!!!]---------------------------------------
  //}------------------------------------------------------------------

  //[VAR]
  //{
      int   caretLineStartIndex;

      int   caretIndexWidth;

      int   caretX, caretY;

      int   caretLineNumber;

      bool  caretAlwaysView = false;

      //[2012.06.13.수][추가!!!]
      bool  isSelArea = false;

  //}


  //[선택영역 해제]
  //{
      //[2010.06.29.화][중요추가!!!]{------------------------------------------------------
      //[되돌리기/되살리기] 의 경우는 _KEY_XXX() 함수를 사용하는 경우가 많은데,
      //_KEY_XXX() 경우는 [선택영역] 을 삭제하고 이 위치에 [입력지정자] 를 위치하게 되는데
      //이 때문에 [되돌리기/되살리기] 가 제대로 해당위치에서 이루어지지 않게 된다.
      //따라서, 반드시 먼저 [선택영역] 을 해제해 주어야 한다.
      //}----------------------------------------------------------------------------------

      //[선택영역 존재 확인]
      //{
          //[102.06.13.수][중요추가!!!]{--------------------------------------
          //둘다 <-1> 이 아닌 경우는 [선택영역] 이 현재 존재하는 것으로 본다.
          //}-----------------------------------------------------------------

          if((_select_start.caret_index >= 0) && (_select_end.caret_index >= 0))
          {
            //[!]{--------------------------------------------------------
            //[선택영역] 이 존재함을 기록.
            //이는 바로 아래의 [선택영역:해제] 부분 뒤에 [다시 그리기] 로
            //즉시 반영할지 여부를 위한것.
            //}-----------------------------------------------------------
            
            isSelArea = true;

          }

      //}

      _Select_CaretIndex(&_select_start, -1); //_select_start.caret_index = -1;
      _select_start.caret_x     = 0;
      _select_start.caret_y     = 0;

      _Select_CaretIndex(&_select_end, -1); //_select_end.caret_index   = -1;
      _select_end.caret_x       = 0;
      _select_end.caret_y       = 0;

      _select_ing               = false;

      //[선택영역 해제 즉시 반영]
      //{
          //[2012.06.13.수][중요추가!!!]{-------------------------
          //[선택영역:해제] 인 경우는 이미 해제된 상태라 아래의
          //<_EDIT_CaretPos()> 함수 안에서 [다시 그리기] 처리를
          //하지 않기 때문에 반드시 여기서 [즉시 반영] 해야 한다.
          //
          //[선택영역] 은 한번만 [해제] 되므로 부하가 없다.
          //}-----------------------------------------------------

          if(isSelArea == true)
          {
            //[선택영역] 해제 반영.
            _EditBuf_Text();

          }

      //}

  //}


  //[입력 지정자 위치 행번호 얻기]{----------------------------------------
  caretLineNumber = STR_Get_LineNumber_withIndex(_editbuf, pCaretIndex);
  //[시작 위치 얻기]-------------------------------------------------------
  //현재 [입력지정자] 가 위치한 행의 시작 위치를 얻는다.
  STR_Get_ThisLineStartIndex(_editbuf, pCaretIndex, &caretLineStartIndex);
  //[<caretindexwidth> 구하기]---------------------------------------------
  _CARETINDEX_CaretIndexWidth(caretLineStartIndex, pCaretIndex,
                              //[2012.04.15.일][수정!!!]
                              //<caretLineStartIndex> 를 사용하지 않고 <caretIndexWidth> 사용.
                              //큰 상관은 없으나 정확하게 구별 하기 위한것.
                              &caretIndexWidth, NULL);
  //[입력지정자 위치 구하기]-----------------------------------------------
  //[문서] 상의 위치를 구한다.
  //[2012.04.15.일][수정!!!]
  //<caretLineStartIndex> 를 사용하지 않고 <caretIndexWidth> 사용.
  //큰 상관은 없으나 정확하게 구별 하기 위한것.
  caretX = caretIndexWidth;
  caretY = caretLineNumber * _line_height;
  //}----------------------------------------------------------------------

  //[입력지정자 위치 설정]
  //{
      //[!]{----------------------------------------------------------------------------
      //[입력지정자] 는 지정 위치에 있어야 한다(실제 선택영역 시작 위치).
      //_EDIT_CaretPos() 함수에서 [선택영역] 이 해제 되지 않도록 처리한다.
      //
      //[2012.06.13.수][중요수정!!!]----------------------------------------------------
      //이미 위에서 [선택영역:해제] 를 했기 때문에 여기서는 [선택영역:해제]
      //방지를 할 필요가 없는데 이제까지 계속 해 왔다.
      //이 경우 [선택영역] 을 설정한 상태에서 [되돌리기/되살리기] 를 하면
      //[선택영역] 은 해제 되었는데 <_EDIT_CaretPos()> 함수에서 <_scroll_ing:true> 인
      //경우는 [선택영역] 이 존재하는 것으로 보고 [다시 그리기] 를 하지 않기 때문에
      //[선택영역] 이 존재하지 않음에도 이전 그려진 것이 그대로 남는 문제를 발견하였다.
      //금일 일단 [주석] 으로 처리해 놓는다.
      //
      //아마도 <_Edit_SelectX()> 를 바탕으로 이 함수를 만들때 그대로 두어서인듯.
      //
      //[참고!!!]-----------------------------------------------------------------------
      //이미 위에서 <isSelArea> 로 구분하여 [선택영역:해제] 인 경우는 [다시 그리기] 를
      //처리 하였으므로 이 부분은 의미 없다.
      //}-------------------------------------------------------------------------------

      //_scroll_ing = true;
      //{
          //반드시 _caretindex 값을 설정해 주어야 한다.
          _caretindex = pCaretIndex;
          _caret_x    = caretX;
          _caret_y    = caretY;

          _EDIT_CaretPos(_caret_x, _caret_y);

      //}
      //_scroll_ing = false;

  //}

  //[입력 지정자 보이기]
  //{
      if(pCaretView == true)
      {
        //[참고!!!]{----------------------------------------------------------
        //일단 [줄이동] 시에는 [다시출력] 하지 않게 만든다.
        //여러 가지가 있으니 사용하지 않는 _edit_paste_ing 사용하여 처리한다.
        //}-------------------------------------------------------------------

        _edit_paste_ing = true;
        //{
            //[중요!!!]{---------------------------------------------------------------------
            //_CARET_ViewAlways() 함수도 같이 사용한다.
            //_Line_View() 함수는 [수평] 으로 [줄이동] 은 하지 않으므로
            //[선택 영역] 이 [수평] 으로 영역을 벗어나 있는 경우는 확실하게 보여주지 못한다.
            //따라서, 먼저 _CARET_ViewAlways() 함수로 확실하게 보이는 영역에 위치 시키고
            //_Line_View() 함수로 여유있게 보이는 위치로 다시 수정해 놓는다.
            //이미 위에서 _edit_paste_ing = true; 로 다시 문서를 출력하지 못하게 만들어
            //놓았으므로 중복출력으로인한 [깜박거림] 현상이 없이 깔끔하게 처리된다.
            //}------------------------------------------------------------------------------

            //먼저 확실하게 보이게 만든다(수평/수직 둘다 처리).
            caretAlwaysView = _CARET_ViewAlways(false);

        //}
        _edit_paste_ing = false;

      }

  //}

  //[선택영역 반영]
  //{
      //[!]{-------------------------------------
      //[선택영역] 은 이미 없지만 다시 그려준다.
      //}----------------------------------------

      if(caretAlwaysView == true) { _EditBuf_Text(); }

  //}

}

void __fastcall Teditor_edit_Form::History_SelectX(//선택 시작 위치.
                                                   int    pSelStartIndex,
                                                   //선택 끝 위치.
                                                   int    pSelEndIndex,
                                                   //true 인경우는 항상 [선택 영역] 을 항상 보이는 위치에 있게 한다.
                                                   bool   pSelView,
                                                   //[선택영역] 의 [시작행] 을 반환한다.
                                                   int   *rStartLineNumber,
                                                   //다시 그려줄지(true)/말지(false)를 결정한다.
                                                   bool   pReDraw,
                                                   //[2009.05.08.금][추가!!!]
                                                   //[입력지정자] 위쪽 보기 설정.
                                                   bool   pAlwaysTopMiddle,
                                                   //[입력지정자] 아래쪽 보기 설정.
                                                   bool   pAlwaysBottomMiddle)
{
  //[2009.02.17.화][생성!!!]{----------------------------------------------------------
  //_Edit_SelectX() 함수를 그대로 사용하고 [선택영역] 을 보여줄지 말지등
  //[되돌리기/되살리기] 기능을 위한 특수 기능을 추가한것이다.
  //이는 [문자열] 을 삭제하는 경우는 반드시 해당 [문자열] 을 [선택영역] 으로
  //지정하고 [선택영역 삭제] 하는 경우나, [문자열] 을 추가 하기 위하여 [입력지정자] 를
  //지정 위치로 이동 시키는데도 이 함수를 사용할수 있다.
  //}----------------------------------------------------------------------------------

  //[VAR]
  //{
      int  start_LineStartIndex;

      int  end_LineStartIndex,
           end_LineEndIndex;

      int  start_CaretIndexWidth,
           end_CaretIndexWidth;

      int  start_CaretX, start_CaretY;
      int  end_CaretX, end_CaretY;

      int  moonjaCount, col;

      //[선택 영역 관리]{------
      //선택 시작 행번호.
      int  selStartLineNumber;
      //선택 끝 행번호.
      int  selEndLineNumber;
      //}----------------------

      //[2009.05.06.수][추가!!!]
      bool  caretAlwaysView = false;


  //}

  //[행번호 얻기]
  //{
      //[시작 행번호 구하기]{----------------------------------------------------------------------------
      //[행번호] 는 꼭 [선택영역] 이 같은행에 있지 않을수 있으므로 각각 별도 계산한다.
      selStartLineNumber = STR_Get_LineNumber_withIndex(_editbuf, pSelStartIndex);
      //[시작 행번호 반환]-------------------------------------------------------------------------------
      //이 함수를 사용하는 곳에서 [선택영역] 을 항상 보여 주게 하기 위하여 [행번호]
      //가 필요하므로 이 선택영역 시작 [행번호] 를 반환해 준다.
      if(rStartLineNumber != NULL) { (*rStartLineNumber) = selStartLineNumber; }
      //[끝 행번호 반환]---------------------------------------------------------------------------------
      //행정보를 얻는 것은 시간을 많이 깍아 먹으므로 이전 행 수부터 다시 시작한다.
      selEndLineNumber   = selStartLineNumber +
                           //이전 행수에 다음 부터 CRLF 의 개수를 더하면 된다.
                           STR_Get_CRLF_Count_withStartEndIndex(_editbuf, pSelStartIndex, pSelEndIndex);
      //}------------------------------------------------------------------------------------------------

  //}

  //[시작/끝 위치 얻기]
  //{
      //[시작위치]{----------------------------------------------------------------
      //현재 행의 시작 위치를 얻는다.
      STR_Get_ThisLineStartIndex(_editbuf, pSelStartIndex, &start_LineStartIndex);
      //[끝위치]-------------------------------------------------------------------
      STR_Get_ThisLineStartIndex(_editbuf, pSelEndIndex, &end_LineStartIndex);
      //}--------------------------------------------------------------------------

  //}

  //[입력지정자 위치 얻기]
  //{
      //[설명]{--------------------------------------------------------------
      //[선택영역] 을 [문서] 의 [지정범위] 에서  가상적으로 만드는 것이므로,
      //실제로 [입력지정자] 의 위치를 정확하게 계산하여 해당 정보 관리변수에
      //할당해 주어야 한다.
      //}--------------------------------------------------------------------

      //[caretindexwidth 구하기]
      //{
          //[시작위치]{------------------------------------------------------
          _CARETINDEX_CaretIndexWidth(start_LineStartIndex, pSelStartIndex,
                                      &start_CaretIndexWidth, &moonjaCount);
          //[끝위치]---------------------------------------------------------
          _CARETINDEX_CaretIndexWidth(end_LineStartIndex, pSelEndIndex,
                                      &end_CaretIndexWidth, &col);
          //}----------------------------------------------------------------

      //}

      //[입력지정자 위치 구하기]
      //{
          //[시작위치]{-------------------------------------
          //[문서] 상의 위치를 구한다.
          start_CaretX = start_CaretIndexWidth;
          start_CaretY = selStartLineNumber * _line_height;
          //[끝위치]----------------------------------------
          //[문서] 상의 위치를 구한다.
          end_CaretX = end_CaretIndexWidth;
          end_CaretY = selEndLineNumber * _line_height;
          //}-----------------------------------------------

      //}

  //}

  //[선택영역 정보 설정]
  //{
      //[시작위치]{-------------------------------
      _Select_CaretIndex(&_select_start, pSelStartIndex); //_select_start.caret_index = pSelStartIndex;
      _select_start.caret_x     = start_CaretX;
      _select_start.caret_y     = start_CaretY;
      //[끝위치]----------------------------------
      _Select_CaretIndex(&_select_end, pSelEndIndex); //_select_end.caret_index   = pSelEndIndex;
      _select_end.caret_x       = end_CaretX;
      _select_end.caret_y       = end_CaretY;
      //}-----------------------------------------

  //}

  //[입력지정자 위치 설정]
  //{
      //[입력지정자] 는 지정 위치에 있어야 한다(실제 선택영역 시작 위치).
      //_EDIT_CaretPos() 함수에서 [선택영역] 이 해제 되지 않도록 처리한다.
      _scroll_ing = true;
      //{
          //[열 표시]{------------------------------------------
          //위에서 얻은 [열] 위치 값을 기록해 주어야 한다.
          //아래 _EDIT_CaretPos() 안에서는 _raw 만 계산이 된다.
          _col = col;
          //}---------------------------------------------------

          //반드시 _caretindex 값을 설정해 주어야 한다.
          _caretindex = _select_start.caret_index;
          _caret_x    = _select_start.caret_x;
          _caret_y    = _select_start.caret_y;

          _EDIT_CaretPos(_caret_x, _caret_y);

      //}
      _scroll_ing = false;

  //}

  //[선택 영역 보이기]
  //{
      if(pSelView == true)
      {
        //[참고!!!]{----------------------------------------------------------
        //일단 [줄이동] 시에는 [다시출력] 하지 않게 만든다.
        //여러 가지가 있으니 사용하지 않는 _edit_paste_ing 사용하여 처리한다.
        //}-------------------------------------------------------------------

        _edit_paste_ing = true;
        //{
            //[중요!!!]{---------------------------------------------------------------------
            //_CARET_ViewAlways() 함수도 같이 사용한다.
            //_Line_View() 함수는 [수평] 으로 [줄이동] 은 하지 않으므로
            //[선택 영역] 이 [수평] 으로 영역을 벗어나 있는 경우는 확실하게 보여주지 못한다.
            //따라서, 먼저 _CARET_ViewAlways() 함수로 확실하게 보이는 영역에 위치 시키고
            //_Line_View() 함수로 여유있게 보이는 위치로 다시 수정해 놓는다.
            //이미 위에서 _edit_paste_ing = true; 로 다시 문서를 출력하지 못하게 만들어
            //놓았으므로 중복출력으로인한 [까박거림] 현상이 없이 깔끔하게 처리된다.
            //}------------------------------------------------------------------------------

            //먼저 확실하게 보이게 만든다(수평/수직 둘다 처리).
            //[2009.05.08.금][수정!!!]
            //보이는 영역의 위치를 설정할수 잇는 보다 강력한 함수로 대체한다.
            caretAlwaysView = _Caret_ViewAlways_Middle(pAlwaysTopMiddle, pAlwaysBottomMiddle);

        //}
        _edit_paste_ing = false;

      }

  //}

  //[선택영역 반영]
  //{
      //[!]{--------------------------------------------------------------
      //[선택영역] 을 반영하기 위하여 유일하게 여기서 한번 다시 그려준다.
      //단, 처리를 요청한 경우만 처리한다.
      //}-----------------------------------------------------------------

      if((pReDraw == true) || (caretAlwaysView == true)) { _EditBuf_Text(); }

  //}

  return;

}

void __fastcall Teditor_edit_Form::History_SelectDelete(void)
{
  //[2007.03.07.수][생성!!!]{-------------------------------------------------
  //_EDIT_SelectDelete() 함수를 그대로 다시 만든것으로 [되돌림/되살림] 기능을
  //분리 사용하기 위하여 다시 만든다.
  //}-------------------------------------------------------------------------

  //[VAR]
  //{
      struct CARETINFO   select_start;
      struct CARETINFO   select_end;

  //}

  //[선택영역 존재 확인]
  //{
      //[선택영역] 이 없는 경우는 바로 종료한다.
      if(_SELECT_Get_StartEndIndex(&select_start, &select_end) != true) return;

  //}

  //[선택영역 삭제]
  //{
      //[2009.05.03.일][중요수정!!!]{--------------------------------------------
      //_KEY_Delete() 함수 자체내부 적으로 [수정이력] 이 추가되나 여기서는
      //[되돌리기/되살리기] 용도로 사용하므로 [수정이력] 을 추가하지 않도록한다.
      //}------------------------------------------------------------------------

      _KEY_Delete(false);

  //}

  return;

}

void __fastcall Teditor_edit_Form::History_Insert(char  *pInsertStr,
                                                  //[2009.05.07.목][추가!!!]
                                                  //다시그리는 경우는 true.
                                                  bool   pReDraw)
{
  //[2007.03.07.수][생성!!!]{--------------------------------------------------------------
  //_EDIT_Paste() 함수를 그대로 사용한다.
  //단지, [되돌림/되살림] 기능 용으로 분리 사용하기 위하여 별도 함수로 다시 만들어 놓는다.
  //
  //[2012.05.24.목][수정!!!]---------------------------------------------------------------
  //[2012.06.01.금][수정!!!]---------------------------------------------------------------
  //}--------------------------------------------------------------------------------------

  //[VAR]
  //{
      int    i;

      //전달받은 문자열의 길이.('\0' 은 제외한 길이)
      int    size;

      int    crlf_count = 0;

      struct CARETINFO  select_start;
      struct CARETINFO  select_end;

      //_CARET_ViewAlways() 함수가 내부적으로 동작한 경우 true 로 된다.
      bool   caretAlwaysView = false;
      bool   select_use      = false;

      //[2012.06.11.월][추가!!!]
      //<_CommentBlock_Info()> 의 결과를 보관.
      bool   cmtBlkChanged = false;

  //}

//[2012.05.31.목][임시문장]
//msg_msg_Form->_PrintAddLine(0, "History_Insert");

  //[<Shift> 해제]{--------------------------------------------------------------
  //<Shift> 는 문자 입력시 무효하므로 [선택영역] 의 해제를 위하여 기록을 지운다.
  //이렇게 하는 이유는 _EDIT_CaretPos() 함수안의 [선택영역] 처리부분을 참고한다.
  _shift_down = false;
  //}----------------------------------------------------------------------------

  //[선택영역 처리]
  //{
      //[설명]{-----------------------------------------------
      //1. 일단 [선택영역] 구간을 _editbuf[] 상에서 삭제한다.
      //2. [붙이기] 동작을 처리한다.
      //}-----------------------------------------------------

      //먼저 [입력지정자] 의 위치를 [선택영역] 시작 지점으로 이동시킨다.
      if(_SELECT_Get_StartEndIndex(&select_start, &select_end) != true) goto PASTE;

      //[입력지정자 위치 수정]
      //{
          //[!]{-----------------------------------------------------------
          //[선택영역] 이 있는 경우만 처리한다.
          //[입력지정자] 위치는 select_startindex 위치가 된다.(작은 index)
          //}--------------------------------------------------------------

          _caretindex = select_start.caret_index;
          _caret_x    = select_start.caret_x;
          _caret_y    = select_start.caret_y;

          //[입력지정자 위치 조정]
          _EDIT_CaretPos(_caret_x, _caret_y);

      //}

      //[입력지정자 항상 보이기]
      //{
          _editbuf_text_no = true;
          //{
              //[!]{-----------------------------------------------------------------------
              //키는 항상 눈에 보이는 위치에 있어야 한다.
              caretAlwaysView = _CARET_ViewAlways(false);
              //<키> 를 처리하지 않고 여기서 종료 되므로 이곳에서 한번 실행해 주어야 한다.
              //}--------------------------------------------------------------------------
          //}
          _editbuf_text_no = false;

      //}

      //[선택영역 정보 복구]
      //{
          //[!]{----------------------------------------------------------------------------
          //위에서 처리한 _EDIT_CaretPos() 에서 해제된 [선택영역] 의 정보를 다음 처리부에서
          //삭제할수 있도록 이미 얻어 놓은 정보로 복구한다.
          //}-------------------------------------------------------------------------------

          _select_start = select_start;
          _select_end   = select_end;

      //}

      //[선택영역] 삭제.
      if(_SELECT_Delete(&select_start, &crlf_count) == true)
      {
        //[선택영역] 을 처리했다는 것을 알린다.
        select_use = true;

        //[행수 수정]
        //{
            //CRLF 가 삭제된 것이 있는 경우만 수정한다.
            if(crlf_count > 0) { _linecount -= crlf_count; }

        //}

        //[묶음주석 정보 수집]
        //{
            //[2012.06.10.일][추가!!!]{---------------
            //반드시 [수정] 된 후에 [수집] 해야 한다.
            //}---------------------------------------

            //계속 이어지므로 여기서는 처리하지 않는다.
            //[2012.06.12.화][수정!!!]
            //부분정보 수집----------------------v
            //cmtBlkChanged = _CommentBlock_Info(true);

        //}

        //[삭제 반영]{----------------------------------------------------------------------
        //이 문자키의 경우는 한줄만 다시 그려지므로 여기서 처리하지 않으면
        //삭제된 내용이 반영되지 않는다.(반드시 여기서 처리한다)
        //_EditBuf_Text();
        //[2007.03.10.토][수정!!!]
        //여기서 처리 하지 않고 중복 처리를 방지하기 위하여 이 함수 끝에서 한번만 처리한다.
        //}---------------------------------------------------------------------------------

        //[수직스크롤설정]
        //{
            //[!]{----------------------------------------------------------------
            //수정된 행이 있는 경우는 문서행수가 바뀌었으므로 [수직스크롤] 을
            //새로 설정해 주어야 한다.
            //일반 키입력시에는 행이 바뀌지 않으므로 행이 바뀐 이곳에서 처리한다.
            //}-------------------------------------------------------------------

            if(crlf_count > 0) { _Scroll_Resize(); }

        //}

      }

      goto CONTINUE;

  //}

  //----------------------------------------------------------------------------
  //[순수한 "붙이기" 처리]------------------------------------------------------
  //----------------------------------------------------------------------------

  PASTE:

  //[입력지정자 항상 보이기]
  //{
      //[!]{--------------------------------------------------------
      //_EditBuf_Text() 함수가 중복 처리 되는 것을 막기 위한것이다.
      //이 함수 끝에서 한번만 직접 처리하게 만든다.
      //}-----------------------------------------------------------

      _edit_paste_ing = true;
      //{
          //[!]{---------------------------------------------------
          //키는 항상 눈에 보이는 위치에 있어야 한다.
          //[주의!!!]
          //문서가 수정되기 전에 미리 해 주어야 정확하게 동작한다.
          caretAlwaysView = _CARET_ViewAlways(false);
          //}------------------------------------------------------
      //}
      _edit_paste_ing = false;

  //}

  CONTINUE:

  //[문자열 크기 얻기]
  //{
      size = strlen(pInsertStr);

  //}

  //[포함된 행수 구하기]
  //{
      crlf_count = STR_Get_CRLF_Count_withStartEndIndex(pInsertStr, 0, size - 1);

  //}

  //[공간 만들기]
  //{
      //[참고!!!]{---------------------------------------------------------------------
      //for() 문을 사용하여 공간을 만드는 것은 문서량이 많은 경우 시간이 많이 걸리므로
      //_tempbuf[] 와 memmove() 함수를 사용하여 복사 방식으로 처리한다.
      //}------------------------------------------------------------------------------

      //끼워 넣을 시작위치부터 [문서끝] 까지의 [문자열] 을 _tempbuf[] 에 대피시킨다.
      memmove(_tempbuf, &(_editbuf[_caretindex]), _filesize - _caretindex);

      //끼워넣을 공간 다음에 다시 복사해서 붙여준다.
      memmove(&(_editbuf[_caretindex + size]), _tempbuf, _filesize - _caretindex);

  //}

  //[끼워넣기]
  //{
      //비워진 공간에 전달받은 문자열을 끼워 넣는다.
      //memmove() 를 사용하여 고속으로 [복사] 한다.
      memmove(&(_editbuf[_caretindex]), pInsertStr, size);

  //}

  //[후처리]
  //{
      //[문서량수정]
      //{
          //추가한 문자의 길이만큼 [문서량] 이 는다.
          _filesize += size;

      //}

      //[행수 수정]
      //{
          //<CRLF> 가 삭제된 것이 있는 경우만 수정한다.
          if(crlf_count > 0) { _linecount += crlf_count; }

      //}

      //[묶음주석 정보 수집]
      //{
          //[2012.06.10.일][추가!!!]{---------------
          //반드시 [수정] 된 후에 [수집] 해야 한다.
          //}---------------------------------------

          //[2012.06.12.화][수정!!!]
          //부분정보 수집--------------------v
          cmtBlkChanged = _CommentBlock_Info(true);

      //}

      //[수정 반영]
      //{
          //[선택영역] 이 삭제된 경우는 <키> 를 처리하지 않고 여기서 [종료] 하게
          //되므로 이곳에서 직접 수정된 내용을 반영해 주어야 한다.
          if((pReDraw == true) || (caretAlwaysView == true)) { _EditBuf_Text(); }

      //}

      //[수직스크롤설정]
      //{
          //[!]{------------------------------------------------------------
          //수정된 행이 있는 경우는 문서행수가 바뀌었으므로 [수직스크롤] 을
          //새로 설정해 주어야 한다.(여기서 종료하므로 이곳에서 처리한다)
          //}---------------------------------------------------------------

          if(crlf_count > 0) { _Scroll_Resize(); }

      //}

  //}

  //[입력지정자 위치 지정]
  //{
      //[2009.05.09.토][추가!!!]{-------------------------------------------------------
      //붙여넣기한 문자열 끝에 [입력지정자] 를 위치 시킨다.
      //행이 추가됬을수도 있으므로 반드시 _Scroll_Resize() 가 끝난 이위치에서 처리한다.
      //}-------------------------------------------------------------------------------

      //[입력지정자] 위치 수정(붙여넣기한 문자열 끝으로 이동).
      _caretindex += size;

      //[입력지정자] 이동.
      History_SetCaretPos(_caretindex, true);

  //}
  
  //[실시간 선언 정보판 관련]
  //{
      //[단어 구간 정보 추출]
      //{
          //[2012.05.24.목][추가!!!]{---------------------------------------------
          //실시간으로 [입력지정자] 가 위치한 [단어] 의 [시작/끝:위치] 를 관리.
          //
          //[2012.06.01.금][설명!!!]----------------------------------------------
          //<_EDITBUF_LINE_Out()> 에서 [실시간 선언 정보판:대상단어] 를 지정할때
          //<_wordStartIndex/_wordEndIndex> 정보를 사용하므로 항상 수집해 놓는다.
          //}---------------------------------------------------------------------

          STR_Get_WordBound(_editbuf, _filesize, _caretindex,
                            &_wordStartIndex,
                            &_wordEndIndex);

      //}

      //[실시간 선언 정보판 감추기]
      //{
          //[2012.05.24.목][추가!!!]{----------------------------
          //[실시간 선언 정보판] 이 보이는 경우만 처리하고
          //처리후 반드시 [단어지정] 을 위하여 [입력지정자] 가
          //위치한행만 다시 그린다.
          //
          //더불어, <info_tree_Form->_AutoHide_WordBound()> 에서
          //기존 [단어 구간] 을 벗어난 경우는 자동으로 감춰진다.
          //}----------------------------------------------------

          if(info_tree_Form != NULL)
          {
            if((info_tree_Form->Visible == true) &&
               //[2012.06.01.금][추가!!!]
               //<_AutoHide_WordBound()> 함수 사용 허가상태만 처리.
               (info_tree_Form->_sw_AutoHide_WordBound == true))
            {
              //현재 [단어 구간 정보] 전달.
              info_tree_Form->_AutoHide_WordBound(_wordStartIndex, _wordEndIndex);

              //현재 [입력지정자] 가 위치한 행만 다시 그린다.
              _EditBuf_LineText(_row, false);

            }

          }

      //}
      
  //}

}

void __fastcall Teditor_edit_Form::History_FileSave(char  *pFileFullName)
{
  //[2009.05.05.화][생성!!!]{-----------------------------------------------------------------
  //전달받은 [문서경로] 를 바탕으로 [수정이력] 내용을 <*.urd> 문서로 같은 경로에 저장한다.
  //
  //(1) pFileFullName + ".urd" 로 확장자를 교체하는 것이 아니라 아예 확장자를 붙여준다.
  //(2) 새로 얻은 문서로 [수정이력] 정보를 정리하여 저장한다(2진문서).
  //
  //_TEXTINFO_Restore() 함수에서만 호출되어 사용된다.
  //
  //[주의!!!]---------------------------------------------------------------------------------
  //이 것은 문서가 수정되는 경우만 의미가 있으므로 [읽기전용] 인 경우는 처리하지 않는다.
  //또한, 항상 현재 열려있는 문서만을 대상으로 하므로 [편집기] 현재 속성만 검사하여 처리한다.
  //<_readOnly>, <_readOnlyAll> 두개의 속성을 검사하면 간단하게 알수 있다.
  //}-----------------------------------------------------------------------------------------

  //[VAR]
  //{
      //<*.urd> 문서의 경로를 저장한다.
      char   fileName[OPT_filepath_length];
      char   tempWord[OPT_wordStrSize];

      //저장할 문서를 정리하기 위한 공간(동적 생성하여 사용한다).
      char  *fileBuf = NULL;

      int    fileSize;

  //}

  //[<읽기전용> 인가?]
  //{
      //[!]{-----------------------------------------------------------------
      //현재 문서가 <읽기전용> 인 경우는 처리하지 않는다.
      //검증시는 전체 문서가 <읽기전용> 이 되므로 이 경우도 처리하지 않는다.
      //}--------------------------------------------------------------------

      if((_readOnly == true) || (_readOnlyAll == true)) return;

  //}

  //[문서이름 구분 처리]
  //{
      //[!]{-------------------------------------------------------------
      //[새문서] 인 경우는 별도 경로로 [문서이름] 을 합성해 주어야 한다.
      //처음 6 byte 만 읽어서 저장하면 쉽게 확인할수 있다.
      memmove(tempWord, pFileFullName, 6);
      //문자열로 만든다.
      tempWord[6] = '\0';
      //}----------------------------------------------------------------

      if(STR_Match(tempWord, "새문서") == true)
      {
        //"새문서" 라면 실제 [문서이름] 으로 완성해 준다.

        //[임시문서] 의 고정 경로를 할당해 준다.
		STR_Assign(fileName, ((AnsiString)ExtractFilePath(Application->ExeName)).c_str());
        STR_Add(fileName, "temp\\");

        //문서이름 합성.
        STR_Add(fileName, pFileFullName);

      }
      else
      {
        //일반 문서인 경우는 그대로 사용한다.
        STR_Assign(fileName, pFileFullName);

      }

  //}

  //[확장자 붙이기]
  //{
      //[!]{------------------------------------------------------------------------------------
      //<*.urd> 문서이름을 만들어 준다.
      //단, 확장자를 교체하는 것이 아니라 그대로 뒤에 붙여주는 것이다.
      //이는 [새문서] 의 경우는 문서 이름이 "... 새문서.0" 와 같이 확장자가 [문서번호] 가
      //되기때문에 확장자를 다른 것으로 바꾸면 문서를 구분할수 없게 되는 것을 막기 위한 것이다.
      //}---------------------------------------------------------------------------------------

      STR_Add_AB(fileName, fileName, ".urd");

  //}

  //[수정이력 저장]
  //{
      //[저장 구조]{--------------------------------------------------
      //    4Byte         4Byte      |<--------<bufCount>---------|
      //{ [bufCount] + [packetPtr] + [buf[] 의 내용(bufCount 까지)] }
      //|<---------------------<8 + bufCount>---------------------->|
      //}-------------------------------------------------------------

      //[정리 공간 생성]
      //{
          //앞에 4 Byte 정보 두개를 추가하므로 +8 해준다.
          fileSize = 8 + _history.bufCount;
          //fileBuf = new char [fileSize];
          //[동적생성단위적용][2021.01.24.일][수정]
          fileBuf = new char [UnitX(1024, fileSize)];

      //}

      //[선행 정보 정리]
      //{
          *((int *)(&(fileBuf[0]))) = _history.bufCount;
          *((int *)(&(fileBuf[4]))) = _history.packetPtr;

      //}

      //[수정 이력 정리]
      //{
          //현재 <bufCount> 크기 만큼 [수정이력] 내용 전체를 정리한다.
          memmove(&(fileBuf[8]), _history.buf, _history.bufCount);

      //}

      //[문서 저장]
      //{
          //정리된 정보를 <*.urd> 문서로 저장한다.
          FILE_Save(fileName, fileBuf, fileSize);

      //}

      //[임시 저장소 삭제]
      //{
          if(fileBuf != NULL) { delete [] fileBuf; fileBuf = NULL; }

      //}

  //}

}

void __fastcall Teditor_edit_Form::History_FileOpen(char  *pFileFullName)
{
  //[2009.05.05.화][생성!!!]{-----------------------------------------------------------------
  //전달받은 [문서경로] 를 바탕으로 해당하는 <*.urd> 문서를 찾아서 [수정이력] 에 정리해 준다.
  //
  //(1) pFileFullName + ".urd" 로 확장자를 교체하는 것이 아니라 아예 확장자를 붙여준다.
  //(2) 얻은 경로의 <*.urd> 문서를 읽어서 [수정이력] 정보에 정리해준다.
  //
  //_TEXTINFO_Restore() 함수에서만 호출되어 사용된다.
  //
  //[주의!!!]---------------------------------------------------------------------------------
  //이 것은 문서가 수정되는 경우만 의미가 있으므로 [읽기전용] 인 경우는 처리하지 않는다.
  //또한, 항상 현재 열려있는 문서만을 대상으로 하므로 [편집기] 현재 속성만 검사하여 처리한다.
  //<_readOnly>, <_readOnlyAll> 두개의 속성을 검사하면 간단하게 알수 있다.
  //}-----------------------------------------------------------------------------------------

  //[주의!!!]{-------------------------------------------------------------------------------
  //이 함수는 [문서] 를 처음 여는 경우는 호출되어서는 안된다. 처음 여는 문서는 [수정이력] 이
  //존재하지 않기 때문이다.
  //따라서, 이 함수는 이미 열여 있는 문서를 [전환] 시에 다시 여는 경우만 호출해야 한다.
  //}----------------------------------------------------------------------------------------

  //[VAR]
  //{
      //<*.urd> 문서의 경로를 저장한다.
      char   fileName[OPT_filepath_length];
      char   tempWord[OPT_wordStrSize];

      //저장할 문서를 정리하기 위한 공간(동적 생성하여 사용한다).
      char  *fileBuf = NULL;

      int    fileSize;

      int    fileHandle;

  //}

  //[<읽기전용> 인가?]
  //{
      //[!]{-----------------------------------------------------------------
      //현재 문서가 <읽기전용> 인 경우는 처리하지 않는다.
      //검증시는 전체 문서가 <읽기전용> 이 되므로 이 경우도 처리하지 않는다.
      //}--------------------------------------------------------------------

      if((_readOnly == true) || (_readOnlyAll == true)) return;

  //}

  //[문서이름 구분 처리]
  //{
      //[!]{-------------------------------------------------------------
      //[새문서] 인 경우는 별도 경로로 [문서이름] 을 합성해 주어야 한다.
      //처음 6 byte 만 읽어서 저장하면 쉽게 확인할수 있다.
      memmove(tempWord, pFileFullName, 6);
      //문자열로 만든다.
      tempWord[6] = '\0';
      //}----------------------------------------------------------------

      if(STR_Match(tempWord, "새문서") == true)
      {
        //"새문서" 라면 실제 [문서이름] 으로 완성해 준다.

        //[임시문서] 의 고정 경로를 할당해 준다.
        STR_Assign(fileName, ((AnsiString)ExtractFilePath(Application->ExeName)).c_str());
        STR_Add(fileName, "temp\\");

        //문서이름 합성.
        STR_Add(fileName, pFileFullName);

      }
      else
      {
        //일반 문서인 경우는 그대로 사용한다.
        STR_Assign(fileName, pFileFullName);

      }

  //}

  //[확장자 붙이기]
  //{
      //[!]{------------------------------------------------------------------------------------
      //<*.urd> 문서이름을 만들어 준다.
      //단, 확장자를 교체하는 것이 아니라 그대로 뒤에 붙여주는 것이다.
      //이는 [새문서] 의 경우는 문서 이름이 "... 새문서.0" 와 같이 확장자가 [문서번호] 가
      //되기때문에 확장자를 다른 것으로 바꾸면 문서를 구분할수 없게 되는 것을 막기 위한 것이다.
      //}---------------------------------------------------------------------------------------

      STR_Add_AB(fileName, fileName, ".urd");

  //}

  //[수정이력 복구]
  //{
      //[저장 구조]{--------------------------------------------------
      //    4Byte         4Byte      |<--------<bufCount>---------|
      //{ [bufCount] + [packetPtr] + [buf[] 의 내용(bufCount 까지)] }
      //|<---------------------<8 + bufCount>---------------------->|
      //}-------------------------------------------------------------

      //[문서 크기 얻기]
      //{
          //[!]{---------------------------------------------------------------
          //정리할 임시 저장소를 생성하기 위하여 <*.urd> 문서의 크기를 얻는다.
          //내부적으로 <*.urd> 문서가 존재하는지 검사도 같이 수행하므로 반환이
          //false 인 경우는 더이상 처리하지 않고 여기서 종료해야 한다.
          //}------------------------------------------------------------------

          if(FILE_Size(fileName, &fileSize) != true) return;

      //}

      //[정리 공간 생성]
      //{
          //앞에 4 Byte 정보 두개를 추가하므로 +8 해준다.
          //fileBuf = new char [fileSize];
          //[동적생성단위적용][2021.01.24.일][수정]
          fileBuf = new char [UnitX(1024, fileSize)];

      //}

      //[문서 열기]
      //{
          //[읽기 전용] 으로 문서를 연다.
          fileHandle = FileOpen(fileName, fmOpenRead);

          //문서를 읽어들인다.
          FileRead(fileHandle, fileBuf, fileSize);

          //문서를 닫아준다.
          FileClose(fileHandle);

      //}

      //[수정이력 복구]
      //{
          //정리된 정보를 바탕으로 [수정이력] 을 다시 복구해준다.

          _history.bufCount  = *((int *)(&(fileBuf[0])));
          _history.packetPtr = *((int *)(&(fileBuf[4])));

          //현재 <bufCount> 크기 만큼 [수정이력] 내용 전체를 정리한다.
          memmove(_history.buf, &(fileBuf[8]), _history.bufCount);

      //}

      //[임시 저장소 삭제]
      //{
          if(fileBuf != NULL) { delete [] fileBuf; fileBuf = NULL; }

      //}

  //}

}

void __fastcall Teditor_edit_Form::History_EditFileSave(void)
{
  //[2009.05.15.금][생성!!!]{-------------------------------------------
  //현재 편집중인 문서만을 대상으로 이 문서의 [수정이력] 을 저장해준다.
  //}-------------------------------------------------------------------

  if(_textinfo_index < 0) return;

  //현재 문서의 <수정이력> 을 저장한다.
  History_FileSave(_textinfo[_textinfo_index].filename.c_str());

  return;

}

void __fastcall Teditor_edit_Form::History_EditFileOpen(void)
{
  //[2009.05.05.화][생성!!!]{---------------------------------------------------------------
  //무조건 현재 열려있는 문서의 <수정이력> 문서를 열어서 복구해준다.
  //이 함수는 [개발검증] 시에 모든 문서가 [읽기전용] 으로 되어 [개발검증] 시에는
  //문서 전환이 되도 <수정이력> 이 하나도 처리되지 않게 되므로 [개발검증] 에서
  //해제되는 경우 현재 보여지는 문서의 <수정이력> 이 반영되지 않은 생태가 되기 때문이다.
  //따라서, 이 경우 한번 이 함수를 호출하여 현재 보이는 문서의 <수정이력> 을 복구해야 한다.
  //}---------------------------------------------------------------------------------------

  if(_textinfo_index < 0) return;

  //현재 문서의 <수정이력> 을 복구한다.
  History_FileOpen(_textinfo[_textinfo_index].filename.c_str());

  return;

}

void __fastcall Teditor_edit_Form::History_FileDelete(char  *pFileFullName)
{
  //[2009.05.05.화][생성!!!]{-----------------------------------------------------------------
  //전달받은 [문서경로] 를 바탕으로 해당하는 <*.urd> 문서를 찾아서 [삭제] 한다.
  //
  //(1) pFileFullName + ".urd" 로 확장자를 교체하는 것이 아니라 아예 확장자를 붙여준다.
  //(2) 얻은 경로의 <*.urd> 문서를 [삭제] 한다.
  //
  //[주의!!!]---------------------------------------------------------------------------------
  //이 것은 문서가 수정되는 경우만 의미가 있으므로 [읽기전용] 인 경우는 처리하지 않는다.
  //또한, 항상 현재 열려있는 문서만을 대상으로 하므로 [편집기] 현재 속성만 검사하여 처리한다.
  //<_readOnly>, <_readOnlyAll> 두개의 속성을 검사하면 간단하게 알수 있다.
  //}-----------------------------------------------------------------------------------------

  //[VAR]
  //{
      //<*.urd> 문서의 경로를 저장한다.
      char   fileName[OPT_filepath_length];
      char   tempWord[OPT_wordStrSize];

  //}

  //[<읽기전용> 인가?]
  //{
      //[!]{-----------------------------------------------------------------
      //현재 문서가 <읽기전용> 인 경우는 처리하지 않는다.
      //검증시는 전체 문서가 <읽기전용> 이 되므로 이 경우도 처리하지 않는다.
      //}--------------------------------------------------------------------

      if((_readOnly == true) || (_readOnlyAll == true)) return;

  //}

  //[문서이름 구분 처리]
  //{
      //[!]{-------------------------------------------------------------
      //[새문서] 인 경우는 별도 경로로 [문서이름] 을 합성해 주어야 한다.
      //처음 6 byte 만 읽어서 저장하면 쉽게 확인할수 있다.
      memmove(tempWord, pFileFullName, 6);
      //문자열로 만든다.
      tempWord[6] = '\0';
      //}----------------------------------------------------------------

      if(STR_Match(tempWord, "새문서") == true)
      {
        //"새문서" 라면 실제 [문서이름] 으로 완성해 준다.

        //[임시문서] 의 고정 경로를 할당해 준다.
		STR_Assign(fileName, ((AnsiString)ExtractFilePath(Application->ExeName)).c_str());
        STR_Add(fileName, "temp\\");

        //문서이름 합성.
        STR_Add(fileName, pFileFullName);

      }
      else
      {
        //일반 문서인 경우는 그대로 사용한다.
        STR_Assign(fileName, pFileFullName);

      }

  //}

  //[확장자 붙이기]
  //{
      //[!]{------------------------------------------------------------------------------------
      //<*.urd> 문서이름을 만들어 준다.
      //단, 확장자를 교체하는 것이 아니라 그대로 뒤에 붙여주는 것이다.
      //이는 [새문서] 의 경우는 문서 이름이 "... 새문서.0" 와 같이 확장자가 [문서번호] 가
      //되기때문에 확장자를 다른 것으로 바꾸면 문서를 구분할수 없게 되는 것을 막기 위한 것이다.
      //}---------------------------------------------------------------------------------------

      STR_Add_AB(fileName, fileName, ".urd");

  //}

  //[존재확인]
  //{
      //[삭제] 하려는 문서가 존재하지 않는다면 더이상 처리하지 않는다.
      if(FileExists(fileName) != true) return;

  //}

  //[문서 삭제]
  //{
      //지정된 문서를 삭게한다.
      DeleteFile(fileName);

  //}

  return;

}

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

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

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

  //[휠동작]
  //{
      if((bool)GetAsyncKeyState(VK_CONTROL) == true)
      {
        //[2010.06.27.일][추가!!!]-------------------
        //<Ctrl> 이 눌린경우는 [쪽단위] 로 처리한다.
        //}------------------------------------------

        if     (WheelDelta > 0)
        {
          _KEY_PageUp();

        }
        else if(WheelDelta < 0)
        {
          _KEY_PageDown();

        }

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

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

        }

      }

  //}

  return;

}

void __fastcall Teditor_edit_Form::FormMouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
  //[2006.11.28.화][생성!!!]{----------------------------------------------
  //[휠마우스] 를 사용하게 하기 위하여 반드시 포커스를 주어야 한다.
  //
  //[2007.02.06.화][추가!!!]-----------------------------------------------
  //[선택영역] 처리를 추가한다.
  //
  //[2007.02.11.일][추가!!!]-----------------------------------------------
  //이미 [선택영역] 이 있고, <shift-key> 가 눌린 상태에서 마우스로
  //[선택영역] 을 만드는 경우는 새로 만들지 않고 이전에 만든 [선택영역] 을
  //계속 이어서 형성한다.
  //[선택영역] 의 경우는 마우스 [왼쪽버튼] 인 경우로 한정한다.
  //
  //[2009.05.08.금][추가!!!]-----------------------------------------------
  //[가운데눌림] 의 경우는 현재 <_caretindex> 위치의 단어를 지정해 주는
  //기능을 추가한다.
  //}----------------------------------------------------------------------

  //[VAR]
  //{
      int  line_number;

  //}

  //[<선택 영역 검증식 보기판> 영역인가?]
  //{
      //[2011.06.23.목][추가!!!]{-----------------------------
      //반드시 검증시라 [유효] 하고 [보이는] 경우만 처리한다.
      //}-----------------------------------------------------
      
      if((_dbgView_Enable == true) && (_dbgView_Visible == true) &&
         //[2011.06.30.목][추가!!!
         //반드시 <*.c> 문서의 경우만 처리해야 한다.
         (_fileKind == d_Editor_FileKind_c))
      {
        //[!]{-------------------------------------------------------------------------------
        //이 [검증식 보기판] 영역은 편집기 가장 위에 존재하는 것으로 정의돼 있으므로
        //이 영역을 먼저 처리하고 바로 종료하여 [편집기] 처리로 넘어가지 않게 만들어야 한다.
        //이 영역은 <_DbgView_Shape()> 로 그려지고 표시될때 자동으로 계산된다.
        //}----------------------------------------------------------------------------------

        if((!((0 <= X) && (X <= d_gutter_width))) &&
           ((_dbgView_X <= X) &&(X <= (_dbgView_X + _dbgView_Width))) &&
           ((_dbgView_Y <= Y) &&(Y <= (_dbgView_Y + _dbgView_Height))))
        {
          //[버튼 동작 처리]
          //{
              //[2011.06.29.수][추가!!!]{----------------------------------------------
              //버튼은 [영역] 에 [엄지그림] 형식으로 배치된 것으로 실제 버튼이 아니다.
              //따라서, 여기서 직접 영역을 검사하여 해당 영역의 개체를 조정한다.
              //}----------------------------------------------------------------------

              //[기본/고정 보기 전환]
              //{
                  if((((_dbgView_bmp_Close_TRect.left + _dbgView_X) <= X) && (X <= (_dbgView_bmp_Close_TRect.Right  + _dbgView_X))) &&
                     (((_dbgView_bmp_Close_TRect.Top  + _dbgView_Y) <= Y) && (Y <= (_dbgView_bmp_Close_TRect.Bottom + _dbgView_Y))))
                  {
                    //눌린 것으로 표시한다.
                    _DbgView_bmp_Close_Down(true);

                    //버튼을 처리한 경우는 다른 것을 처리하지 않는 것으로 독립성을 부여한다.
                    return;

                  }

              //}

              //[선택 검증식으로 이동]
              //{
                  if((((_dbgView_bmp_GoBlock_TRect.left + _dbgView_X) <= X) && (X <= (_dbgView_bmp_GoBlock_TRect.Right  + _dbgView_X))) &&
                     (((_dbgView_bmp_GoBlock_TRect.Top  + _dbgView_Y) <= Y) && (Y <= (_dbgView_bmp_GoBlock_TRect.Bottom + _dbgView_Y))))
                  {
                    //눌린 것으로 표시한다.
                    _DbgView_bmp_GoBlock_Down(true);

                    //버튼을 처리한 경우는 다른 것을 처리하지 않는 것으로 독립성을 부여한다.
                    return;

                  }

              //}

          //}

          return;

        }
        else if(((_dbgView_bmp_AddBtn_TRect.Left <= X) &&(X <= (_dbgView_bmp_AddBtn_TRect.Left + _dbgView_bmp_AddBtn_TRect.Width())))  &&
                ((_dbgView_bmp_AddBtn_TRect.Top  <= Y) &&(Y <= (_dbgView_bmp_AddBtn_TRect.Top  + _dbgView_bmp_AddBtn_TRect.Height()))) &&
                //반드시 '+' 인 상태만 처리해야 한다.
                (_dbgView_State == '+'))
        {
          //[201.07.10.일][추가!!!]{-------------------
          //[검증식 추가 버튼] 이 눌린것으로 표기한다.
          //}------------------------------------------

          _DbgView_bmp_AddBtn_Down(true);

          //버튼을 처리한 경우는 다른 것을 처리하지 않는 것으로 독립성을 부여한다.
          return;

        }

      }

  //}

  if(Button == mbLeft)
  {
    //[왼쪽 버튼] 만으로 한정한다.

    //[정지점 설정]
    //{
        //[2007.04.12.목][추가!!!]
        //[검증판] 영역인 경우는 현재 지정행에 [정지점] 을 설정하거나 해제해 주어야 한다.
        if((0 <= X) && (X <= d_gutter_width))
        {
          //[정지점 설정 가능 상태 검사]
          //{
              //[2009.04.29.수][추가!!!]{--------------------------------------------------
              //현재 [검증개발] 상태가 아니라면 [정지점] 을 설정할수 없다는 것을 알려준다.
              //[알림창] 은 [모달] 속성으로 사용자가 계속 닫아 주어야 하므로, 불편을 주지
              //않기 위하여 [귀뜸말] 로 대신한다. 계속 나와도 자동으로 사라지므로 좋다.
              //}--------------------------------------------------------------------------

              //if(ide_buttons_Form->_tabs->_tabindex != 1)
              //[2009.12.28.월][수정!!!]
              //[재검증] 탭이 하나 추가 되었으므로 관련 부분을 수정한다.
              if(!((ide_buttons_Form->_tabs->_tabindex == 1) || (ide_buttons_Form->_tabs->_tabindex == 2)))
              {
                //현재는 [정지점] 을 설정할수 없는 상태라는 것을 알려준다.

                ide_hint_Form->_ShowHint_EditDebugPanel
                (ide_editor_Form->Left + d_gutter_width - 1,
                ide_editor_Form->Top + editor_top_Form->Height + Y - (Y % _line_height) + 1,
                 "[정지점] 은 [개발검증] 상태일 경우만 설정가능합니다."
                );

                return;

              }

          //}

          //현재 [행 번호] 를 구한다.
          line_number = (Y - _text_org_y) / _line_height;

          //[[정지점] 설정/해제]
          //{
              //[2009.04.30.목][수정!!!]{-------------------------------------------------------------
              //오류등이 발생한 경우 간단한 [알림글] 을 보여주기 위하여 [귀뜸말] 을
              //보여주는 에 이때 [귀뜸말] 이 위치할 좌표를 같이 전달해 주는 것으로 수정한다.
              //이는 [정지점] 은 수시로 설정될수 있는데 오류가 발생할때마다 [모달] 속성을 가진
              //[알림글] 을 보여주면 사용자가 일일히 닫아 주어야 하므로 번거롭다. 따라서,
              //굳이 닫거나 신경쓰지 않아도 자동으로 사라지는 [귀뜸말] 을 사용하여 알림글을 보여준다.
              //}-------------------------------------------------------------------------------------

              _BREAKPOINT_Set(ide_editor_Form->Left + d_gutter_width - 1,
                              //정확하게 행에 지정되도록 처리한다.
                              ide_editor_Form->Top + editor_top_Form->Height + Y - (Y % _line_height) + 1,
                              line_number);

          //}

          return;

        }

    //}

    //[상태기록]{-------------------------------------------------------------------------
    //[마우스] 가 눌린 것이다.
    _mouse_down = true;
    //[촛점갖기]--------------------------------------------------------------------------
    //[2012.04.27.금][주석처리!!!]
    //이미 [촛점] 이 있는 경우는 WM_SETFOCUS 의 중복처리 방지를 위하여 처리하지 않는다.
    //if(this->Focused() != true){ this->SetFocus(); }
    //[입력지정자 위치 지정]--------------------------------------------------------------
    //[입력지정자] 위치를 현재 찍은 위치로 수정한다.
    _CARETPOS_MouseDown(X, Y);
    //[촛점갖기]--------------------------------------------------------------------------
    //[2012.04.27.금][수정!!!]
    //<_CARETPOS_MouseDown()> 보다 다음에 처리하는 것으로 수정.
    //이는 [이전위치] 가 [잠깐보이고 사라지는] 잔상을 막기 위한 것이다.
    //<_CARETPOS_MouseDown()> 로 먼저 [입력지정자] 위치가 확정된 뒤에 [촛점] 을 맞추면
    //<WM_SETFOCUS> 처리부에서 이전 위치자체가 바로 [현재위치] 가 되어 [잔상] 이 발생하지
    // 않는다.
    if(this->Focused() != true){ this->SetFocus(); }
    //}-----------------------------------------------------------------------------------


    //[단어 선택 영역 만들기]
    //{
        //[2011.05.11.수][추가!!!]{-------------------------------------------------------
        //<Ctrl + 마우스(L)> 인 경우는 현재 단어를 [선택영역] 으로 지정해 준다.
        //
        //[주의!!!]-----------------------------------------------------------------------
        //<Ctrl> 만 되고, <Alt> 나 <Shift> 는 눌리지 않은 상태여야 한다.
        //<Ctrl + Alt> 의 조합의 경우는 [마우스 줄이동] 의 경우이므로 섞이지 않아야 한다.
        //
        //반드시 아래의 [선택영역 처리] 보다 먼저 처리되어야 한다.
        //그렇지 않은 경우는 [선택영역] 이 제대로 유지 되지 못한다.
        //}-------------------------------------------------------------------------------

        if(((bool)GetAsyncKeyState(VK_CONTROL) == true) && //<Ctrl-Key> 이어야 하고
           ((bool)GetAsyncKeyState(VK_MENU) != true) &&    //<Alt-Key>  는 아니어야 한다.
           (_shift_down != true))                          //<Shift-Key>  는 아니어야 한다.
        {
          //현재 <_caretindex> 위치의 [단어] 를 [선택영역] 으로 지정한다.
          _Mouse_WordSelect();

          //아래의 [선택영역 처리] 는 이 경우와 겹치지 않으므로 더이상 처리하지 않는다.
          return;

        }

    //}


    //[선택영역 처리]
    //{
        //[설명]{-----------------------------------------------------------------------------
        //[마우스] 가 처음 down 된 지점부터 일단은 [선택영역] 이 시작된 것으로 간주해야 한다.
        //단, <shift-key> 가 눌린 상태라면, 이전에 형성된 [선택영역] 을 계속 이어간다.
        //}-----------------------------------------------------------------------------------

        //[선택영역] 형성이 시작됬음을 알린다.
        _select_ing = true;

        //[예외처리]
        //{
            //[2007.02.11.일][추가!!!]
            //이미  [선택영역] 이 있고 <shift-key> 가 눌린 경우는 초기화 하지 않고 계속 이어간다.
            if((_select_start.caret_index >= 0) && (_select_end.caret_index >= 0) && (_shift_down == true)) return;

        //}

        //[선택영역반영]
        //{
            //새로 시작하는 것이므로 현재 [선택영역] 이 있는 경우는 해제한다.
            if((_select_start.caret_index >= 0) && (_select_end.caret_index >= 0))
            {
              //[선택영역] 은 caret_index 가 둘중 하나라도 -1 인 경우는 처리되지 않으므로
              //일단 둘다 -1 로 해 놓는다.
              _Select_CaretIndex(&_select_start, -1); //_select_start.caret_index = -1;
              _Select_CaretIndex(&_select_end, -1); //_select_end.caret_index   = -1;

              //[선택영역] 이 해제된 것을 반영하기 위하여 다시 그린다.
              _EditBuf_Text();

            }

        //}

        //이 시작위치는 현재 [입력지정자] 의 위치가 된다.
        _Select_CaretIndex(&_select_start, _caretindex); //_select_start.caret_index = _caretindex;
        _select_start.caret_x     = _caret_x;
        _select_start.caret_y     = _caret_y;

        //[영역초기화]
        //{
            //여기서 _select_endindex 는 -1 로 초기화해 주어야 이전에 설정된 것을 완전히
            //무효화 하고 새로 시작할수 있다(지금 새로운 [선택영역] 이 시작된 것이므로...).
            _Select_CaretIndex(&_select_end, -1); //_select_end.caret_index = -1;
            _select_end.caret_x     = 0;
            _select_end.caret_y     = 0;

        //}

    //}

  }
  else if(Button == mbMiddle)
  {
    //[2009.05.08.금][추가!!!]{----------------------------------------------------------
    //현재 [입력지정자] 를 포함하고 있는 [단어] 를 추출하고 [선택영역] 으로 지정해준다.
    //원래 [다중눌림] 의 경우 처리 되어야 하지만 BCB 에서 이 기능이 원활하게 동작되지
    //않으므로 확실하게 동작되나 잘 사용되지 않는 [가운데눌림] 으로 대체한다.
    //어차피 이 기능 이외에는 사용되는 기능이 없으므로...
    //}---------------------------------------------------------------------------------

    //[촛점갖기]------------------------------------------------------------------------
    //이미 [촛점] 이 있는 경우는 WM_SETFOCUS 의 중복처리 방지를 위하여 처리하지 않는다.
    if(this->Focused() != true) { this->SetFocus(); }
    //}---------------------------------------------------------------------------------

    //[입력지정자 위치 지정]{-----------------------------------
    //[입력지정자] 위치를 현재 찍은 위치로 수정한다.
    //이는 _Mouse_WordSelect() 함수가 <_caretindex> 를 사용하여
    //[단어] 를 지정하게 되므로 반드시 먼저 수행되어야 한다.
    _CARETPOS_MouseDown(X, Y);
    //[단어 지정]-----------------------------------------------
    //현재 <_caretindex> 위치의 [단어] 를 지정해준다.
    _Mouse_WordSelect();
    //}---------------------------------------------------------

  }

  //[지정자 묶음 감추기]{-----------
  //[2007.11.30.금][추가!!!]
  //[지정자] 를 보이지 않게 만든다.
  DEBUG_Indicator_Hide();
  //}-------------------------------

  return;

}

void __fastcall Teditor_edit_Form::FormMouseMove(TObject *Sender,
      TShiftState Shift, int X, int Y)
{
  //[2007.02.06.화][생성!!!]{---------------------------------------------------------------
  //마우스를 집어끌어서 [선택영역] 을 지정하기 위하여 사용된다.
  //(_block_ing == true) 인 경우만 처리가 유효하다.
  //
  //[2007.02.08.목][추가!!!]----------------------------------------------------------------
  //마우스로 [선택영역] 을 만들어 가는 도중 [편집기] 안의 영역을 벗어나는 경우는
  //자동으로 [줄이동] 을 하여 항상 [입력지정자] 가 눈에 보이는 위치에 있도록 만들어야 한다.
  //
  //[선택영역] 의 경우는 마우스 [왼쪽버튼] 인 경우로 한정한다.
  //
  //[2007.02.26.월][추가!!!]----------------------------------------------------------------
  //마우스로 한번 찍는 경우 Down 으로 그치지 않고 이곳 Move 가지 들어 오게 된다.
  //이때 (움직이지는 않은 경우) 이 함수에서 [선택영역] 끝 위치가 지정되는 것을 막기 위하여
  //[입력지정자] 위치에 변화가 없는 경우는 Move 는 아닌것으로 보고 [선택영역] 끝 위치를
  //처리하지 않는다.
  //
  //[2007.04.10.화][추가!!!]----------------------------------------------------------------
  //[표시지정자] 의 모양을 해당 영역에 따라 다르게 지정해야 한다.
  //이는 [편집기] 안에 [검증창] 이 있고 이 영역은 편집영역이 아니기 때문이다.
  //}---------------------------------------------------------------------------------------

  //[VAR]
  //{
      //[2007.02.26.월][추가!!!]
      bool  caret_pos_changed = false;

      //[2011.05.06.금][추가!!!]{------------------------
      //[영역별 줄이동] 을 위한 [줄이동 양] 을 저장한다.
      //이 값은 실시간으로 계산되어야 한다.
      int   scrollSize;
      //}------------------------------------------------

  //}

  //[Ctrl + 마우스 이동으로 탐색]
  //{
      //[2010.08.28.토][추가!!!]{------------------------------------------
      //현재 [편집기] 상의 [화면지정자:Y] 위치를 계속 기록해 놓는다.
      //이는 <Ctrl> 이 눌린 경우 해당 위치를 바로 기록해 놓기 위한 것이다.
      //}------------------------------------------------------------------

      _mousePosY = Y;

  //}

  //[표시지정자 모양 전환]
  //{
      //[2007.04.10.화][추가!!!]{-------------------------------------
      //[표시지정자] 의 모양을 [검증창/편집기] 에 따라 바꾸어야 한다.
      //}-------------------------------------------------------------

      if((0 <= X) && (X <= d_gutter_width))
      {
        //일반 화살표 모양으로 바꾼다.
        if(this->Cursor != crDefault) this->Cursor = crDefault;

      }
      else
      {
        if((_dbgView_Enable == true) && (_dbgView_Visible == true) &&
           //[2011.06.30.목][추가!!!
           //반드시 <*.c> 문서의 경우만 처리해야 한다.
           (_fileKind == d_Editor_FileKind_c))
        {
          //[2011.06.23.목][추가!!!]{----------------------------------------------------------
          //이 [검증식 보기판] 영역은 편집기 가장 위에 존재하는 것으로 정의돼 있으므로
          //이 영역을 먼저 처리하고 바로 종료하여 [편집기] 처리로 넘어가지 않게 만들어야 한다.
          //이 영역은 <_DbgView_Shape()> 로 그려지고 표시될때 자동으로 계산된다.
          //}----------------------------------------------------------------------------------

          if     (((_dbgView_X <= X) &&(X <= (_dbgView_X + _dbgView_Width))) &&
                  ((_dbgView_Y <= Y) &&(Y <= (_dbgView_Y + _dbgView_Height))))
          {
            //일반 화살표 모양으로 바꾼다.
            if(this->Cursor != crDefault) this->Cursor = crDefault;

          }
          else if(((_dbgView_bmp_AddBtn_TRect.Left <= X) &&(X <= (_dbgView_bmp_AddBtn_TRect.Left + _dbgView_bmp_AddBtn_TRect.Width()))) &&
                  ((_dbgView_bmp_AddBtn_TRect.Top  <= Y) &&(Y <= (_dbgView_bmp_AddBtn_TRect.Top  + _dbgView_bmp_AddBtn_TRect.Height()))))
          {
            //[201.07.10.일][추가!!!]{--------------------------------------------
            //[검증식 추가 버튼] 의 경우도 동일한 [화면지정자] 모양으로 처리한다.
            //}-------------------------------------------------------------------

            //일반 화살표 모양으로 바꾼다.
            if(this->Cursor != crDefault) this->Cursor = crDefault;

          }
          else
          {
            //[2011.07.01.금][추가!!!]
            //모양을 편집용 모양으로 만든다.
            if(this->Cursor != crIBeam) this->Cursor = crIBeam;


            //[검증식 추가 버튼 무효]
            //{
                //[2011.07.10.일][추가!!!]{------------------------------
                //이 경우는 [검증식 추가 버튼] 영역을 벗어난 것으로 보고
                //눌린 것이 있다면 해제시킨다.
                //}------------------------------------------------------

                //계속 그려지지 않도록 복수처리를 방지한다.
                if(_dbgView_bmp_AddBtn_Down == true)
                {
                  _DbgView_bmp_AddBtn_Down(false);

                }

            //}

          }

        }
        else
        {
          //[2011.07.01.금][추가!!!]
          //모양을 편집용 모양으로 만든다.
          if(this->Cursor != crIBeam) this->Cursor = crIBeam;

        }

      }

  //}

  //[<선택 영역 검증식 보기판> 영역인가?]
  //{
      //[2011.06.23.목][추가!!!]{-----------------------------
      //반드시 검증시라 [유효] 하고 [보이는] 경우만 처리한다.
      //}-----------------------------------------------------

      if((_dbgView_Enable == true) && (_dbgView_Visible == true) &&
         //[2011.06.30.목][추가!!!
         //반드시 <*.c> 문서의 경우만 처리해야 한다.
         (_fileKind == d_Editor_FileKind_c))
      {
        //[!]{-------------------------------------------------------------------------------
        //이 [검증식 보기판] 영역은 편집기 가장 위에 존재하는 것으로 정의돼 있으므로
        //이 영역을 먼저 처리하고 바로 종료하여 [편집기] 처리로 넘어가지 않게 만들어야 한다.
        //이 영역은 <_DbgView_Shape()> 로 그려지고 표시될때 자동으로 계산된다.
        //}----------------------------------------------------------------------------------

        if(((_dbgView_X <= X) &&(X <= (_dbgView_X + _dbgView_Width))) &&
           ((_dbgView_Y <= Y) &&(Y <= (_dbgView_Y + _dbgView_Height))))
        {
          //[!]{-------------------------------------------------------------------------------
          //[버튼] 이 눌린 경우라면 [버튼] 영역을 벗어난 경우는 자동으로 눌린 것을 해제시킨다.
          //어떤 버튼인지는 중요하지 않으며 모든 버튼 영역을 벗어났는지만 중요하다.
          //해당하는 경우 한번만 처리하면 된다.
          //}----------------------------------------------------------------------------------

          //[기본/고정 보기 전환]
          //{
              if((((_dbgView_bmp_Close_TRect.left + _dbgView_X) <= X) && (X <= (_dbgView_bmp_Close_TRect.Right  + _dbgView_X))) &&
                 (((_dbgView_bmp_Close_TRect.Top  + _dbgView_Y) <= Y) && (Y <= (_dbgView_bmp_Close_TRect.Bottom + _dbgView_Y))))
              {
                //아직 버튼 영역인 경우다.
                return;

              }

          //}

          //[선택 검증식으로 이동]
          //{
              if((((_dbgView_bmp_GoBlock_TRect.left + _dbgView_X) <= X) && (X <= (_dbgView_bmp_GoBlock_TRect.Right  + _dbgView_X))) &&
                 (((_dbgView_bmp_GoBlock_TRect.Top  + _dbgView_Y) <= Y) && (Y <= (_dbgView_bmp_GoBlock_TRect.Bottom + _dbgView_Y))))
              {
                //아직 버튼 영역인 경우다.
                return;

              }

          //}

          //[벗어난 경우처리]
          //{
              //[!]{------------------------------------------------
              //여기까지 온것은 모든 버튼 영역을 벗어난 경우다.
              //이전에 눌린 것이 어떤 것이었는지 구분하여 처리한다.
              //}---------------------------------------------------

              if     (_dbgView_bmp_Close_Down == true)
              {
                _DbgView_bmp_Close_Down(false);

              }
              else if(_dbgView_bmp_GoBlock_Down == true)
              {
                _DbgView_bmp_GoBlock_Down(false);

              }

          //}

          return;

        }

      }

  //}

  if(Shift.Contains(ssLeft))
  {

    //[선택영역]
    //{
        //[!]{----------------------------------------------------------------------------
        //반드시 (_select_ing == true) 로 [선택영역] 이 형성되는 과정에서만 처리해야한다.
        //또한, [마우스] 가 눌린 상태인 경우만 처리한다.
        //이는 [키] 로 영역을 만드는 과정에서 아래를 처리하지 않기 위함이다.
        //}-------------------------------------------------------------------------------

        if((_mouse_down == true) && (_select_ing == true))
        {
          //[설명]{----------------------------------------------------------------
          //_select_endindex 를 계속 설정하고 이 값이 수정되는 경우는 계속 다시
          //[선택영역] 을 반영해 주어야 한다.
          //이것은 현재 보이는 [편집기] 의 내용을 다시 출력하면 자동으로 적용된다.
          //}----------------------------------------------------------------------

          //[편집기 영역 확인]
          //{
              //[!]{-------------------------------------------------------------------------
              //[편집영역] 을 벗어난 경우는 자동으로 [줄이동] 을 수행하여 [입력지정자] 가
              //항상 보이는 위치에 있도록 만든다.
              //아래 각각의 함수내부에서 자동으로 자신이 처리할 부분인지 확인하여 처리하므로
              //굳이 여기서 벗어났는지 확인하여 처리할 필요는 없다.
              //}-----------------------------------------------------------------------------

              _SELECTSCROLL_Up(Y);
              _SELECTSCROLL_Down(Y);
              _SELECTSCROLL_Left(X);
              _SELECTSCROLL_Right(X);

              //전부다 수정한다.(마우스가 움직인 만큼 한꺼번에 수정될수 있어야 한다.)
          //}

          //[입력지정자 위치 지정]
          //{
              //[입력지정자] 위치를 현재 찍은 위치로 수정한다.
              //위치가 바뀌었는지 결과를 같이 얻는다.
              caret_pos_changed = _CARETPOS_MouseDown(X, Y);

          //}

          //[2007.02.26.월][수정!!!]
          //[입력지정자] 의 위치변화가 있는 경우만 처리한다.(쓸데없는 시간 낭비도 줄일수 있다.)
          if(caret_pos_changed == true)
          {
            //[선택영역 끝 위치 구하기]
            //{
                //마지막 위치는 현재 설정된 [입력지정자] 의 위치가 된다.
                _Select_CaretIndex(&_select_end, _caretindex); //_select_end.caret_index = _caretindex;
                _select_end.caret_x     = _caret_x;
                _select_end.caret_y     = _caret_y;

            //}

            //[반영]{-------------------------------------------
            //문서를 다시 출력하는 것으로 자동반영 되도록 한다.
            _EditBuf_Text();
            //}-------------------------------------------------

          }

        }

    //}

  }

  //[Ctrl + Alt + 마우스 이동으로 탐색]
  //{
      //[2010.08.28.토][추가!!!]{---------------------------------------------------
      //[굴림] 장치가 없는 마우스를 위하여 <Ctrl + 마우스 상/하 움직임> 의 조합으로
      //[굴림이동] 과 같은 동작을 구현하기 위한 것이다.
      //
      //[2010.09.05.일][수정!!!]----------------------------------------------------
      //<Ctrl + Alt> 조합으로 수정한다.
      //}---------------------------------------------------------------------------

      //<Ctrl + Alt> 키가 눌린 경우만 처리해야 한다.
      if(((bool)GetAsyncKeyState(VK_CONTROL) == true) && ((bool)GetAsyncKeyState(VK_MENU) == true))
      {
        //[2010.09.05.일][수정!!!]{------------------------------------------------
        //그냥 사용하면 너무 민감하게 동작하므로 위 아래로 <_line_height> 만큼
        //여유를 준다.
        //그렇지 않은 경우, 복사, 붙이기 시에 <Ctrl> 을 누르면 원치 않게 위/아래로
        //줄이동이 이루어져 불편하다.
        //}------------------------------------------------------------------------

        //[영역별 줄이동수 얻기]
        //{
            //[2011.05.06.금][중요수정!!!]{-------------------------
            //각 [영역] 마다 서로 다른 [줄이동양] 을 적용해야 한다.
            //[가장 왼쪽 1/5]   : 1줄씩 이동.
            //[가장 오른쪽 1/5] : 1장씩 이동.
            //[나머지 중간]     : 기본 설정으로 이동.
            //}-----------------------------------------------------

            if     (X <(this->Width/5))
            {
              //[가장 왼쪽 1/5] 의 영역은 1줄씩 이동한다.
              scrollSize = 1;

            }
            else if(X > (this->Width - this->Width/5))
            {
              //[가장 오른쪽 1/5] 의 영역은 1장씩 이동한다.
              scrollSize = ((editor_edit_Form->Height - editor_info_Form->Height) / editor_edit_Form->_line_height);

            }
            else
            {
              //가장 넓은 가운데 영역은 기본 줄단위로 이동한다.
              scrollSize = 5;

            }

        //}

        if     ((_mousePosY_Ctrl - 2) > Y)
        {
          //[!]{-------------------------------------------------------------
          //<Ctrl> 이 눌린 위치보다 위쪽으로 움직인 경우는, 위로 줄이동한다.
          //일반적인 [굴림이동] 과 동일한 줄수를 이동시킨다.
          //}----------------------------------------------------------------

          ide_editor_Form->_scroll_v_Form->_Position(ide_editor_Form->_scroll_v_Form->_position - scrollSize);

        }
        else if((_mousePosY_Ctrl + 2) < Y)
        {
          //[!]{-----------------------------------------------------------------
          //<Ctrl> 이 눌린 위치보다 아래쪽으로 움직인 경우는, 아래로 줄이동한다.
          //일반적인 [굴림이동] 과 동일한 줄수를 이동시킨다.
          //}--------------------------------------------------------------------

          ide_editor_Form->_scroll_v_Form->_Position(ide_editor_Form->_scroll_v_Form->_position + scrollSize);

        }

      }

  //}

}

void __fastcall Teditor_edit_Form::FormMouseUp(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
  //[2007.02.06.화][생성!!!]{----------------------------------
  //[선택영역] 이 형성되고 있는 상태라면 여기서 종료해야 한다.
  //
  //[선택영역] 의 경우는 마우스 [왼쪽버튼] 인 경우로 한정한다.
  //}----------------------------------------------------------

  //[VAR]
  //{
      //[2007.02.26.월][추가!!!]
      bool  caret_pos_changed = false;

  //}
  
  //[<선택 영역 검증식 보기판> 영역인가?]
  //{
      //[2011.06.23.목][추가!!!]{-----------------------------
      //반드시 검증시라 [유효] 하고 [보이는] 경우만 처리한다.
      //}-----------------------------------------------------

      if((_dbgView_Enable == true) && (_dbgView_Visible == true) &&
         //[2011.06.30.목][추가!!!
         //반드시 <*.c> 문서의 경우만 처리해야 한다.
         (_fileKind == d_Editor_FileKind_c))
      {
        //[!]{-------------------------------------------------------------------------------
        //이 [검증식 보기판] 영역은 편집기 가장 위에 존재하는 것으로 정의돼 있으므로
        //이 영역을 먼저 처리하고 바로 종료하여 [편집기] 처리로 넘어가지 않게 만들어야 한다.
        //이 영역은 <_DbgView_Shape()> 로 그려지고 표시될때 자동으로 계산된다.
        //}----------------------------------------------------------------------------------

        if((!((0 <= X) && (X <= d_gutter_width))) &&
           ((_dbgView_X <= X) &&(X <= (_dbgView_X + _dbgView_Width))) &&
           ((_dbgView_Y <= Y) &&(Y <= (_dbgView_Y + _dbgView_Height))))
        {
          //[2011.06.27.월][수정!!!]{------------------
          //상태에 따라 구분 처리하는 것으로 수정한다.
          //}------------------------------------------

          //[버튼 동작 처리]
          //{
              //[2011.06.29.수][추가!!!]{----------------------------------------------
              //버튼은 [영역] 에 [엄지그림] 형식으로 배치된 것으로 실제 버튼이 아니다.
              //따라서, 여기서 직접 영역을 검사하여 해당 영역의 개체를 조정한다.
              //}----------------------------------------------------------------------

              //[기본/고정 보기 전환]
              //{
                  if((((_dbgView_bmp_Close_TRect.left + _dbgView_X) <= X) && (X <= (_dbgView_bmp_Close_TRect.Right  + _dbgView_X))) &&
                     (((_dbgView_bmp_Close_TRect.Top  + _dbgView_Y) <= Y) && (Y <= (_dbgView_bmp_Close_TRect.Bottom + _dbgView_Y))))
                  {
                    if(_dbgView_bmp_Close_Down == true)
                    {
                      //전용 처리 함수를 호출하여 처리한다.
                      _Event_dbgView_bmp_Close();

                      //눌린 것을 원상복구한다.
                      _DbgView_bmp_Close_Down(false);

                    }

                    //버튼을 처리한 경우는 다른 것을 처리하지 않는 것으로 독립성을 부여한다.
                    return;

                  }

              //}

              //[선택 검증식으로 이동]
              //{
                  if((((_dbgView_bmp_GoBlock_TRect.left + _dbgView_X) <= X) && (X <= (_dbgView_bmp_GoBlock_TRect.Right  + _dbgView_X))) &&
                     (((_dbgView_bmp_GoBlock_TRect.Top  + _dbgView_Y) <= Y) && (Y <= (_dbgView_bmp_GoBlock_TRect.Bottom + _dbgView_Y))))
                  {
                    if(_dbgView_bmp_GoBlock_Down == true)
                    {
                      //전용 처리 함수를 호출하여 처리한다.
                      _Event_dbgView_bmp_GoBlock();

                      //눌린 것을 원상복구한다.
                      _DbgView_bmp_GoBlock_Down(false);

                    }

                    //버튼을 처리한 경우는 다른 것을 처리하지 않는 것으로 독립성을 부여한다.
                    return;

                  }

              //}

          //}

          switch(_dbgView_State)
          {
            case '+' :
            {
              //[선택된 검증식] 을 계산하고 펼쳐서 결과를 보여준다.
              _DbgView_Exe();

            } break;

            case '-' :
            {
              //[검증식] 의 표기형식을 [2/10/16진수/문자열] 로 순서대로 계속 전환해 준다.
              //계산역시 다시 하게 된다.

              //[2018.07.24.화][수정!!!]{-------------------------------------------
              //[마우스:오른쪽버튼] 인 경우만 처리.
              //이는 [문자열 전제보기:더블클릭] 인 경우와 확실하게 구분하기 위한것.
              //자세한 내용은 같은 날짜의 주석을 참고.
              //}-------------------------------------------------------------------

              if(Button == mbRight)
              {
                _DbgView_ModeChange();

              }

            } break;

            case 'x' :
            {
              //아무 처리도 하지 않는다.

            } break;

          }

          //더이상 처리하지 않는다.
          return;

        }
        else if(((_dbgView_bmp_AddBtn_TRect.Left <= X) &&(X <= (_dbgView_bmp_AddBtn_TRect.Left + _dbgView_bmp_AddBtn_TRect.Width()))) &&
                ((_dbgView_bmp_AddBtn_TRect.Top  <= Y) &&(Y <= (_dbgView_bmp_AddBtn_TRect.Top  + _dbgView_bmp_AddBtn_TRect.Height()))) &&
                //반드시 '+' 인 상태만 처리해야 한다.
                (_dbgView_State == '+'))
        {
          //[201.07.10.일][추가!!!]{----------------------------------------------------------
          //[검증식 추가 버튼] 의 경우로 현재 선택된 [검증식] 을 [검증식 보기창] 에 추가한다.
          //관련 처리가 복잡 하므로 별도의 함수로 처리한다.
          //}---------------------------------------------------------------------------------

          if(_dbgView_bmp_AddBtn_Down == true)
          {
            //전용 처리 함수를 호출하여 처리한다.
            _Event_dbgView_bmp_AddBtn();

            //눌린 것을 원상복구한다.
            _DbgView_bmp_AddBtn_Down(false);

          }

          //버튼을 처리한 경우는 다른 것을 처리하지 않는 것으로 독립성을 부여한다.
          return;

        }

      }

  //}

  switch(Button)
  {
    case mbLeft :
    {
      //[선택영역종료]
      //{
          //[선택영역] 형성의 종료를 알린다.
          _select_ing = false;

      //}

      //[상태기록]
      //{
          //[마우스] 가 더이상 눌린 상태가 아니다.
          _mouse_down = false;

      //}

    } break;

    case mbRight :
    {
      //[정지점 전체 삭제]
      //{
          //[2009.04.29.수][추가!!!]{----------------------
          //현재 설정되 있는 모든 [정지점] 을 삭제해 준다.
          //}----------------------------------------------

          if((0 <= X) && (X <= d_gutter_width))
          {
            //모든 [정지점] 을 삭제하고 반영해 준다.
            Debug_BpList_DeleteAll();

            //다른 처리는 하지 않는다.
            return;

          }

      //}

      //[팝업메뉴] 를 보여준다.

      //[동작함수 등록]
      //{
          _popup_menu_->_EVENT_ItemSelect = _EVENT_PopupMenu;

      //}

      //[투명기능 설정]
      //{
          //[2009.05.09.토][생성!!!]{----------------------
          //이 것을 가진 부품의 [투명기능] 을 같이 가진다.
          //}----------------------------------------------

          _popup_menu_->AlphaBlend      = main_Form->AlphaBlend;
          _popup_menu_->AlphaBlendValue = main_Form->AlphaBlendValue;

      //}

      _popup_menu_->_Popup(main_Form->Left + ide_editor_Form->Left + this->Left + X,
                           main_Form->Top  + ide_editor_Form->Top  + this->Top  + Y);

    } break;

  }

  return;

}

void __fastcall Teditor_edit_Form::FormDblClick(TObject *Sender)
{
  //[2018.07.24.화][생성!!!]{---------------------------------------
  //[검증식 보기판] 항목이 문자열인 경우 [문자열 전체보기] 를 처리.
  //}---------------------------------------------------------------

  //[VAR]
  //{
      TPoint  thisPos;

      TPoint  mousePos;

      int     X, Y;

  //}

  //[X, Y 얻기]
  //{
      //[<그림부품:절대위치> 얻기]
      //{
          //[주의!!!]{---------------------------------------------------------------------------------
          //<ClientOrigin> 는 정확한 값이나, 같은 기능으로 알려진 <ClientToScreen()> 은 정확하지 않다.
          //}------------------------------------------------------------------------------------------

          thisPos = this->ClientOrigin;

      //}

      //[<화면지정자:절대위치> 얻기]
      //{
          GetCursorPos(&mousePos);

      //}

      X = mousePos.x - thisPos.x;

      Y = mousePos.y - thisPos.y;

  //}

  //[<선택 영역 검증식 보기판> 영역인가?]
  //{
      //[!]{--------------------------------------------------
      //반드시 검증시라 [유효] 하고 [보이는] 경우만 처리한다.
      //}-----------------------------------------------------

      if((_dbgView_Enable == true) && (_dbgView_Visible == true) &&
         //반드시 <*.c> 문서의 경우만 처리해야 한다.
         (_fileKind == d_Editor_FileKind_c))
      {
        //[!]{-------------------------------------------------------------------------------
        //이 [검증식 보기판] 영역은 편집기 가장 위에 존재하는 것으로 정의돼 있으므로
        //이 영역을 먼저 처리하고 바로 종료하여 [편집기] 처리로 넘어가지 않게 만들어야 한다.
        //이 영역은 <_DbgView_Shape()> 로 그려지고 표시될때 자동으로 계산된다.
        //}----------------------------------------------------------------------------------

        if((!((0 <= X) && (X <= d_gutter_width))) &&
           ((_dbgView_X <= X) &&(X <= (_dbgView_X + _dbgView_Width))) &&
           ((_dbgView_Y <= Y) &&(Y <= (_dbgView_Y + _dbgView_Height))))
        {
          if(_dbgView_State == '-')
          {
            //[!]{----------------------------------------------------------------
            //현재 [문자열] 인 경우는 문자열 보기로 적용.
            //이 함수 처리시 최종적으로 <DebugViewDisplay_Make_DisplayStr()> 에서
            //[문자열 전체보기] 가 처리된다.
            //}-------------------------------------------------------------------

            //[중요!!!]{-----------------------------------------------------------------
            //<_DbgView_Exe()> 함수가 일반적인 [검증식] 용도로도 사용되므로
            //<true> 로 설정해서 [더블클릭:문자열 전체 보기] 용으로 호출됐음을 알려준다.
            _isDblClicked = true;
            //}--------------------------------------------------------------------------

            _DbgView_Exe();

          }

        }

      }

  //}

}

//------------------------------------------------------------------------------
//[검증판]----------------------------------------------------------------------
//------------------------------------------------------------------------------

void __fastcall Teditor_edit_Form::_DEBUG_Init(void)
{
  //[2007.04.08.일][생성!!!]{------------------
  //[검증판] 과 관련된 모든 초기화를 수행한다.
  //
  //[2012.06.08.금][수정!!!]-------------------
  //[2018.09.12.수][수정!!!]-------------------
  //}------------------------------------------

  //[VAR]
  //{
      //배경 bmp 경로.
      AnsiString  bmp_path;

  //}

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

      //그림 영역 크기 설정(정의된 크기를 사용한다).
      _bmp_debug->Width       = d_gutter_width;
      //[2012.06.08.금][수정!!!]
      //항상 [화면높이] 로 유지 하던 것을 [편집기] 크기에 맞게 수정하는 것으로 수정.
      _bmp_debug->Height      = this->Height;//Screen->Height;

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

  //}

  //[정지점]
  //{
      //[2009.04.29.수][수정!!!]
      //{
          //현재 정지점 [유/무효] 상태에 따라 다른 기호를 사용해 주어야 한다.

          if(ide_buttons_Form->_debug_bmpbtns[d_debug_bmpbtn_breakpoint]->_index == 0)
          {
            //[활성화] 된 [정지점] 을 표시하기 위한 bmp 를 만든다.
            bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\8_8\\breakpoint.bmp";

          }
          else
          {
            //[비활성화] 기호를 사용한다.
            bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\8_8\\breakpoint2.bmp";

          }

      //}

      //[정지점] 을 생성한다.
      _bmp_breakpoint_ = new Graphics::TBitmap;

      //그림을 올려준다.(8*8)
      _bmp_breakpoint_->LoadFromFile(bmp_path);

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

  //}

  //[정지점행]
  //{
      //[2018.09.12.수][추가!!!]{-------------------------
      //[정지점행] 을 [반투명] 으로 만들어 주는 BMP 생성.
      //}-------------------------------------------------

      _bmp_BreakPointLine_ = new Graphics::TBitmap;

      _bmp_BreakPointLine_->PixelFormat = pf24bit;

      //크기 지정등은 편집기 크기에 따라 <_BREAKPOINT_Edit_Draw> 에서 자동으로 수행.

  //}

  //[실행 지정자]
  //{
      //[실행 지정자] 를 표시하기 위한 bmp 를 만든다.
      bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\12_12\\run_arrow.bmp";

      //[검증 지정자] 를 생성.
      _bmp_run_arrow_ = new Graphics::TBitmap;

      //그림을 올려준다.(8*8)
      _bmp_run_arrow_->LoadFromFile(bmp_path);

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

  //}

  //[그림색 바꾸기]
  //{
      //그림색을 지정색으로 바꾼다.
      BMP_Self_ChangeColor2(_bmp_breakpoint_, clBlack, IDE_COLOR_breakpoint, clWhite, clWhite);
      BMP_Self_ChangeColor2(_bmp_run_arrow_,  clBlack, IDE_COLOR_run_arrow, clWhite, clWhite);

  //}

  //[속성 초기화]
  //{
      _scroll_y          = 0;
      _run_arrow_visible = false;
      _run_arrow_line    = 0;

  //}

  //[컨트롤 그리기]
  //{
      //컨트롤을 그려서 모양을 만든다.
      _DEBUG_Shape();

  //}

  //[그려준다]
  //{
      //_bmp_ 에 현재 그려진 내용을 출력한다.
      _DEBUG_Draw();

  //}

}

void __fastcall Teditor_edit_Form::_DEBUG_Shape(void)
{
  //[2007.04.08.일][생성!!!]{-------------------------------------------------------
  //이전에는 색을 칠한 뒤 bmp 전체를 "BMP_Brightness(_bmp_debug, 200)" 로 색을 다시
  //전부 바꾸었으나 아예 칠할 색을 수정하여 칠하는 방법을 사용한다.
  //두번 작업 할것을 한번에 끝낼수 있으므로 속도가 빠르다.
  //}-------------------------------------------------------------------------------

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

  //}

  //[내용 그리기]
  //{
      _DEBUG_BreakPoint();
      _DEBUG_RunArrow(_run_arrow_line, false);

  //}

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

  //}

  return ;

}

void __fastcall Teditor_edit_Form::_DEBUG_BreakPoint(void)
{
  //[2007.04.08.일][생성!!!]{-----------------------------------------------
  //[정지점]을 일괄 표시한다.
  //이는 이미 설정되 있는 [정지점] 을 한꺼번에 다시 표시하는 경우 사용된다.
  //}-----------------------------------------------------------------------

  //[VAR]
  //{
      TRect  rect;
      int    color;
      int    i;

  //}

  //[영역정보]
  //{
      rect = _bmp_debug->Canvas->ClipRect;

      rect.Left   = rect.Left;
      rect.Top    = rect.Top + 1;
      rect.Right  = rect.Width()/2 - 1;
      rect.Bottom = rect.Bottom - 1;

  //}

  //[바탕색]
  //{
      //바탕색은 일괄적으로 지운다.

      //칠할 색을 수정한다.
      BMP_Get_Bright_Color(_ide_option->color_0, IDE_BRIGHT_editdebug, &color);

      //밝기가 수정된 색을 칠한다.
      _bmp_debug->Canvas->Brush->Color = color;
      _bmp_debug->Canvas->FillRect(rect);

  //}

  //[모두 보여주기]
  //{
      //[2007.04.12.목][추가!!!]
      for(i = 0; i < _breakpoint.count; i++)
      {
        //단순히 _bmp_ 에 그리는 것 까지만 수행한다.
        //배경은 위에서 한번에 전부 지우므로 개별적으로 지워줄 필요는 없다.
        _BREAKPOINT_DebugPanel_Draw(false, _breakpoint.line[i]);

      }

  //}

  return;

}

void __fastcall Teditor_edit_Form::_DEBUG_RunArrow(int   pLINEnumber,
                                                   bool  pSELFdraw)
{
  //[2007.04.08.일][생성!!!]{--
  //[실행지정자] 를 표시한다.
  //}--------------------------

  //[VAR]
  //{
      TRect  rect;
      int    color;

  //}

  //[복사값 저장]
  //{
      _run_arrow_line = pLINEnumber;

  //}

  //[영역정보]
  //{
      rect = _bmp_debug->Canvas->ClipRect;

      rect.Left   = rect.Width()/2 - 1;
      rect.Top    = rect.Top + 1;
      rect.Right  = rect.Right - 1;
      rect.Bottom = rect.Bottom - 1;

  //}

  //[바탕색]
  //{
      //칠할 색을 수정한다.
      BMP_Get_Bright_Color(_ide_option->color_0, IDE_BRIGHT_editdebug, &color);

      //밝기가 수정된 색을 칠한다.
      _bmp_debug->Canvas->Brush->Color = color;
      _bmp_debug->Canvas->FillRect(rect);

  //}

  //[표시]
  //{
      //보여야 하는 경우만 [실행지정자] 를 보여 주어야 한다.
      if(_run_arrow_visible == true)
      {
        BMP_Copy_Transparent(//출발지 정보.
                             _bmp_run_arrow_, 0, 0, _bmp_run_arrow_->Width, _bmp_run_arrow_->Height,
                             //도착지 정보.
                             _bmp_debug, 15, _scroll_y + (pLINEnumber * _line_height) + 2, _bmp_debug->Width, _bmp_debug->Height,
                             //투명 지정 색.
                             clWhite);

      }

  //}

  //[그리기]
  //{
      //그린 것을 보여준다.
      BitBlt(_bmp_->Canvas->Handle, _bmp_debug->Width/2 - 1, 0,
             _bmp_debug->Width/2, this->Height,
             _bmp_debug->Canvas->Handle, _bmp_debug->Width/2 - 1, 0, SRCCOPY);

  //}       

  //[반영]
  //{
      //독립적으로 사용되는 경우만 그려 주어야 한다.
      if(pSELFdraw == true)
      {
        //[2007.04.09.월][추가!!!]
        //그린 것을 보여준다.
        BitBlt(this->Canvas->Handle,
               _bmp_debug->Width/2 - 1, 0,
               _bmp_debug->Width/2, this->Height,
               _bmp_->Canvas->Handle, _bmp_debug->Width/2 - 1, 0, SRCCOPY);

      }

  //}

  return;

}

void __fastcall Teditor_edit_Form::_DEBUG_RunArrow_Show(void)
{
  //[2007.04.08.일][생성!!!]{--
  //[실행지정자] 를 표시한다.
  //}--------------------------

  _run_arrow_visible = true;

  return;

}

void __fastcall Teditor_edit_Form::_DEBUG_RunArrow_Hide(void)
{
  //[2007.04.08.일][생성!!!]{--
  //[실행지정자] 를 감춘다.
  //}--------------------------

  _run_arrow_visible = false;

  return;

}

void __fastcall Teditor_edit_Form::_DEBUG_Scroll(int  pPOSITION)
{
  //[2007.04.08.일][생성!!!]{-----------------------------
  //스크롤 되는 경우를 처리한다.
  //위치를 수정하여 [정지점/실행지정자] 를 다시 표시한다.
  //}-----------------------------------------------------

  //표시 위치를 수정한다.
  _scroll_y = (-1) * pPOSITION * _line_height;

  //다시 그린다.
  _DEBUG_Shape();

  return;

}

void __fastcall Teditor_edit_Form::_DEBUG_Draw(void)
{
  //[2007.04.08.일][생성!!!]

  BitBlt(_bmp_->Canvas->Handle, 0, 0,
         d_gutter_width, _bmp_->Height,
         _bmp_debug->Canvas->Handle, 0, 0, SRCCOPY);

  return;

}

//[정지점]{---------------------------------------------------------------------

void __fastcall Teditor_edit_Form::_BREAKPOINT_Init(struct BREAKPOINT  *pBREAKpoint)
{
  //[2007.04.12.목][생성!!!]{----------------
  //[정지점] 정보 구조체를 전부 초기화 한다.
  //}----------------------------------------

  //[VAR]
  //{
      int  i;

  //}

  for(i = 0; i < d_breakpoint_max; i++)
  {
    //행은 0 부터 시작하므로 -1 로 초기화 한다.
    pBREAKpoint->line[i] = -1;

  }

  //처음 [정지점] 은 설정되지 않은 상태이다.
  pBREAKpoint->count = 0;

  return;

}

int __fastcall Teditor_edit_Form::_BREAKPOINT_Search(int  pLINEnumber)
{
  //[2007.04.12.목][생성!!!]{--------------------------------
  //지정행을 가진 [정지점] 이 있다면 해당 index 를 반환한다.
  //}--------------------------------------------------------

  //[VAR]
  //{
      int  i;

  //}

  for(i = 0; i < _breakpoint.count; i++)
  {
    if(_breakpoint.line[i] == pLINEnumber)
    {
      //일칙하는 index 를 반환한다.
      return(i);

    }

  }

  //여기까지 온것은 겹치는 것이 없는 것이다.
  return(-1);

}

bool __fastcall Teditor_edit_Form::_BREAKPOINT_Add(int  pLINEnumber)
{
  //[2007.04.12.목][생성!!!]{------------------------
  //[정지점] 정보구조체에 [정지점] 을 하나 추가한다.
  //}------------------------------------------------

  //[VAR]
  //{
      AnsiString  str;

  //}

  //[중복검사]
  //{
      //이미 지정 행이 있는 경우는 처리하지 않는다.
      if(_BREAKPOINT_Search(pLINEnumber) >= 0) return(false);

  //}

  //[정지점 추가]
  //{
      //이미 한계를 넘었다면 처리하지 않는다.
      if(_breakpoint.count < d_breakpoint_max)
      {
        _breakpoint.line[_breakpoint.count] = pLINEnumber;

        _breakpoint.count++;

      }
      else
      {
        //경고한다.

        str = "[정지점] 은 문서당 \"" + IntToStr(d_breakpoint_max) + "개\" 를 넘을 수 없습니다.";

        ide_msgbox_Form->_MsgBox(d_MSGBOX_error, str.c_str());

        //처리할수 없었다는 것을 알려준다.
        return(false);

      }

  //}

  return(true);

}

void __fastcall Teditor_edit_Form::_BREAKPOINT_Delete(int  pLINEnumber)
{
  //[2007.04.12.목][생성!!!]{---------------------------------------------
  //[정지점] 정보구조체에 지정 행정보를 가진 [정지점] 을 하나 삭제한다.
  //
  //[주의!!!]-------------------------------------------------------------
  //index 로 삭제하는 것이 아니라 pLINEnumber 와 일치하는 곳을 삭제하므로
  //빠진곳을 매꾸어 주어야 한다.
  //}---------------------------------------------------------------------

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

  //}

  //[삭제 위치 찾기]
  //{
      //pLINEnumber 값을 가진 [정지점] index 를 찾는다.
      delete_index = _BREAKPOINT_Search(pLINEnumber);

      //해당하지 않는 경우는 처리하지 않는다.
      if(delete_index == -1) return;

  //}

  //[정지점 삭제]
  //{
      //[!]{-----------------------------------------------------------------------------------------
      //뒤의 것을 앞에 연속적으로 덮어쓰는 것으로 간단하게 처리한다.
      //memmove() 함수는 1 byte 단위로 처리 되므로 int 형인 값을 이동하는데 사용하는 것은 좋지 않다.
      //(이동개수)*4 로 크기를 환산하여 사용할수 있지만 모든 곳에서 int(4byte) 가 아닐수 있으므로
      //정확하지 않을수 있다. 따라서 가장 확실하게 for() 문으로 직접 처리한다.
      //}--------------------------------------------------------------------------------------------

      for(i = delete_index; i < _breakpoint.count; i++)
      {
        _breakpoint.line[i] = _breakpoint.line[i + 1];

      }

      _breakpoint.count--;

  //}

  return;

}

void __fastcall Teditor_edit_Form::_BREAKPOINT_DebugPanel_Draw(bool pERASEback,
                                                               int  pLINEnumber)
{
  //[2007.04.12.목][생성!!!]{-----------------------------------
  //실제로 [검증판] 의 지정 위치에 [정지점] 을 그려주기만 한다.
  //_bmp_ 에 출력만 하고 실제 보이는 영역에 출력하지 않는다.
  //}-----------------------------------------------------------

  //[VAR]
  //{
      TRect  rect;
      int    x, y;

      int    color;

  //}

  //[영역정보]
  //{
      //[검증판] 에서 [정지점] 이 그려질 영역 정보를 얻는다.
      //가로*세로 는 모두 행의 높이와 같은 값을 가지는 정사각형 영역으로 설정한다.
      rect = _bmp_debug->Canvas->ClipRect;

      rect.Left   = 1;
      rect.Top    = _scroll_y + (pLINEnumber * _line_height) + 2;
      rect.Right  = rect.Left + _line_height;
      rect.Bottom = rect.Top + _line_height;

  //}

  //[바탕색]
  //{
      if(pERASEback == true)
      {
        //[정지점] 이 그려질 영역만 지운다.

        //칠할 색을 수정한다.
        BMP_Get_Bright_Color(_ide_option->color_0, IDE_BRIGHT_editdebug, &color);

       //밝기가 수정된 색을 칠한다.
        _bmp_debug->Canvas->Brush->Color = color;
        _bmp_debug->Canvas->FillRect(rect);

      }

  //}

  //[정지점 그리기]
  //{
      //[정지점 좌표 계산]{---------------------------------------
      x = 3;
      y = rect.Top + _line_height/2 - _bmp_breakpoint_->Height/2;
      //}---------------------------------------------------------

      BMP_Copy_Transparent(//출발지 정보.
                           _bmp_breakpoint_, 0, 0, _bmp_breakpoint_->Width, _bmp_breakpoint_->Height,
                           //도착지 정보.
                           _bmp_debug, x, y,
                           //폭과 높이는 행의 높이와 같은 것으로 한다.
                           _line_height, _line_height,
                           //투명 지정 색.
                           clWhite);

  //}

  //[반영]
  //{
      //[_bmp_debug] 에 반영한다.
      BitBlt(_bmp_->Canvas->Handle, rect.Left, rect.Top, rect.Width(), rect.Height(),
             _bmp_debug->Canvas->Handle, rect.Left, rect.top, SRCCOPY);

  //}

  return;

}

void __fastcall Teditor_edit_Form::_BREAKPOINT_Set(//지정 위치.
                                                   int  pPosX,
                                                   int  pPosY,
                                                   int  pLINEnumber)
{
  //[2007.04.12.목][생성!!!]{-------------------------------------------------------------
  //실제로 [검증판] 의 지정 위치에 [정지점] 을 그려준다.
  //즉시 보이게 출력하는 것까지 실행한다.
  //
  //[2009.04.25.토][중요수정!!!]----------------------------------------------------------
  //[정지점] 은 [개발검증] 시에만 설정 가능하도록 수정한다.
  //[정지점] 은 일시적인 기능이므로 굳이 편집시에까지 설정할 필요가 없다.
  //
  //[2009.04.30.목][수정!!!]{-------------------------------------------------------------
  //오류등이 발생한 경우 간단한 [알림글] 을 보여주기 위하여 [귀뜸말] 을
  //보여주는 에 이때 [귀뜸말] 이 위치할 좌표를 같이 전달해 주는 것으로 수정한다.
  //이는 [정지점] 은 수시로 설정될수 있는데 오류가 발생할때마다 [모달] 속성을 가진
  //[알림글] 을 보여주면 사용자가 일일히 닫아 주어야 하므로 번거롭다. 따라서,
  //굳이 닫거나 신경쓰지 않아도 자동으로 사라지는 [귀뜸말] 을 사용하여 알림글을 보여준다.
  //}-------------------------------------------------------------------------------------

  //[VAR]
  //{
      TRect  rect;
      int    x, y;

      int    color;

      //[2009.04.26.일][추가!!!]{--------
      //[정지점] 한개의 정보를 관리한다.
      struct  BPITEM  bpItem;
      //}--------------------------------

  //}

  //[<개발검증> 중인지 확인]
  //{
      //[2009.04.25.토][중요수정!!!]{---------------
      //[정지점] 은 [개발검증] 상태에서만 적용된다.
      //}-------------------------------------------

      //현재 [검증개발] 이 아닌 경우는 더이상 처리하지 않고 종료한다.
      //if(ide_buttons_Form->_tabs->_tabindex != 1) return;
      //[2009.12.28.월][수정!!!]
      //[재검증] 탭이 하나 추가 되었으므로 관련 부분을 수정한다.
      if(!((ide_buttons_Form->_tabs->_tabindex == 1) || (ide_buttons_Form->_tabs->_tabindex == 2))) return;

  //}

  //[정지점을 설정할수 있는 상태인가?]
  //{
      //[2009.09.13.일][중요추가!!!]{---------------------------------------------------
      //현재 [자동검증] 중인 경우는 [정지점] 설정이 무의미 하고 실제 [맷돌모듈] 에서는
      //통신중 충돌이 발생하므로 이 경우는 처리하지 않고 종료한다.
      //}-------------------------------------------------------------------------------

      if(Debug_BpList_IsPossible() != true) return;

  //}

  //[설정/해제]
  //{
      //[영역정보]
      //{
          //[검증판] 에서 [정지점] 이 그려질 영역 정보를 얻는다.
          //가로*세로 는 모두 행의 높이와 같은 값을 가지는 정사각형 영역으로 설정한다.
          rect        = _bmp_debug->Canvas->ClipRect;

          rect.Left   = 1;
          rect.Top    = _scroll_y + (pLINEnumber * _line_height) + 2;
          rect.Right  = rect.Left + _line_height;
          rect.Bottom = rect.Top + _line_height;

      //}

      //이미 설정된 행이라면 현재 행의 [정지점] 을 "삭제" 한다.
      if(_BREAKPOINT_Search(pLINEnumber) >= 0)
      {
        //이미 설정되 있는 행이므로 [정지점] 을 "삭제" 해야 한다.

        //[정지점 정보 얻기?]
        //{
            //[2009.04.26.일][추가!!!]{----------------------------
            //삭제를 위하여 현재 위치의 [정지점] 의 정보를 얻는다.
            //}----------------------------------------------------

            if(Debug_BpList_GetItem(pPosX, pPosY, pLINEnumber, &bpItem) != true) { return; }

            //[정지점 삭제]
            //{
                if(Debug_BpList_Delete(&bpItem) != true) { return; }

            //}

        //}

        //[삭제]
        //{
            //[정지점] 을 기록한다.
            //단, 에러가 발생한 경우는 바로 종료한다.
            _BREAKPOINT_Delete(pLINEnumber);

        //}

        //[바탕색]
        //{
            //[정지점] 이 있는 영역을 지워주기만 하면 된다.

            //칠할 색을 수정한다.
            BMP_Get_Bright_Color(_ide_option->color_0, IDE_BRIGHT_editdebug, &color);

            //밝기가 수정된 색을 칠한다.
            _bmp_debug->Canvas->Brush->Color = color;
            _bmp_debug->Canvas->FillRect(rect);

        //}

      }
      else
      {
        //[설정 가능한 지점인가?]
        //{
            //[2009.04.25.토][추가!!!]{---------------------------------------------
            //이 함수내부적으로 실제 사용되는 [정지점] 의 정보를 정리하여 관리한다.
            //만일 [정지점] 을 지정할수 없는 조건이라면 여기서 종료해야 한다.
            //}---------------------------------------------------------------------

            if(Debug_BpList_GetItem(pPosX, pPosY, pLINEnumber, &bpItem) != true) { return; }

            //[정지점 추가]
            //{
                if(Debug_BpList_Add(&bpItem) != true) { return; }

            //}

        //}

        //[추가]
        //{
            //[정지점] 을 기록한다.
            //단, 에러가 발생한 경우는 바로 종료한다.
            if(_BREAKPOINT_Add(pLINEnumber) == false) return;

        //}

        //[바탕색]
        //{
            //[정지점] 이 그려질 영역만 지운다.

            //칠할 색을 수정한다.
            BMP_Get_Bright_Color(_ide_option->color_0, IDE_BRIGHT_editdebug, &color);

            //밝기가 수정된 색을 칠한다.
            _bmp_debug->Canvas->Brush->Color = color;
            _bmp_debug->Canvas->FillRect(rect);

        //}

        //[정지점 그리기]
        //{
            //[정지점 좌표 계산]{---------------------------------------
            x = 3;
            y = rect.Top + _line_height/2 - _bmp_breakpoint_->Height/2;
            //}---------------------------------------------------------

            BMP_Copy_Transparent(//출발지 정보.
                                 _bmp_breakpoint_, 0, 0, _bmp_breakpoint_->Width, _bmp_breakpoint_->Height,
                                 //도착지 정보.
                                 _bmp_debug, x, y,
                                 //폭과 높이는 행의 높이와 같은 것으로 한다.
                                 _line_height, _line_height,
                                 //투명 지정 색.
                                 clWhite);
        //}

      }

  //}

  //[반영]
  //{
      //_bmp_ 에 반영한다.
      BitBlt(_bmp_->Canvas->Handle, rect.Left, rect.Top, rect.Width(), rect.Height(),
             _bmp_debug->Canvas->Handle, rect.Left, rect.top, SRCCOPY);

  //}

  //[반영]
  //{
      //[2007.04.16.월][수정!!!]{---------------------------------------------------
      //다시 출력하는 것으로 반영한다.(이 함수를 사용하는 것이 가장 빠른 방법이다.)
      _EditBuf_Text();
      //}---------------------------------------------------------------------------

      //[참고!!!]{-------------------------------------------------------------------------
      //[정지줄] 도 같이 표시해야 하는데, 이 경우는 그 위에 현재 출력된 문자열도
      //같이 출력해 주어야 한다.
      //문제는 행으로 이 행의 문자열 위치를 얻기 위해서는 CRLF 의 수를 세야 한다는 것이다.
      //이는 문서량이 많은 경우는 많은 시간이 소요되므로 바람직하지 않다.
      //가장 빠른 방법은 _EditBuf_Text() 함수를 사용하여 처리하는 것이다.
      //내부적으로 문자열출력과 [정지줄] 그리기 까지 완전히 자동으로 처리된다.
      //전체를 다시 그리게 되므로 [검증판] 도 다시 자동으로 반영된다.
      //}----------------------------------------------------------------------------------

  //}

  return;

}

void __fastcall Teditor_edit_Form::_BREAKPOINT_Edit_Draw(int  pLINEnumber)
{
  //[2007.04.15.일][생성!!!]{------------------------------------------
  //지정행이 [정지점] 이 설정된 행인 경우는 [편집기] 바탕의 행을
  //지정색으로 칠한다.
  //단, 문자열을 출력하기 전에 처리 되어야 한다.(바탕에 해당하므로...)

  //이 함수는 지정행이 [정지점] 이 있는 행인지는 검사하지 않으므로
  //[정지점] 이 있는 행인 경우만 이 함수를 사용해야 한다.
  //
  //[2018.09.12.수][수정!!!]-------------------------------------------
  //}------------------------------------------------------------------

  //[VAR]
  //{
      TRect  rect;

      //[2018.09.12.수][추가!!!]
      int    w, h;
      bool   dotStart, dot;

  //}

  //[영역 계산]
  //{
      //현재 행의 [사각형] 영역을 구한다.
      rect = _bmp_->Canvas->ClipRect;

      //[왼쪽 좌표]
      //{
          //왼쪽은 [검증판] 영역을 고려하여 위치를 설정한다.
          //_text_org_x 는 이미 d_gutter_width 값이 붙임값으로 적용된 상태이다.
          if(_text_org_x > d_gutter_width) { rect.Left = d_gutter_width + 1; }
          else                             { rect.Left = d_gutter_width;     }

      //}

      //[수직 좌표]
      //{
          //수직 정보를 구한다.
          rect.Top    = _text_org_y + pLINEnumber * _line_height;
          rect.Bottom = rect.Top + _line_height;

      //}

  //}

  //[검사]
  //{
      //보이는 영역인 경우만 처리한다.
      if(!((0 <= rect.Top) && (rect.Top <= _bmp_->Height))) return;

  //}

  /*
  //[정지점 행 그리기]
  //{
      //[2018.09.12.수][주석처리!!!]{----------------------------------------------------
      //이전 안으로 모든 행을 [정지점색] 으로 칠하지만 [배경그림] 을 완전히 가리므로
      //배경 그림이 있는 경우 보기 좋지 않다.
      //따라서, 문자 부분은 가리지만 배경 부분은 [줄이동자 배경과 같은 점] 으로 처리하는
      //방식으로 변경.
      //}--------------------------------------------------------------------------------


      //[편집기] 상의 이 행을 전부 지정색으로 칠한다.
      _bmp_->Canvas->Brush->Color = _breakline_color;
      _bmp_->Canvas->FillRect(rect);

  //}
  */

  //[정지점 행 그리기:새 방법]
  //{
      //[2018.09.12.수][추가!!!]{----------------------------------------------------
      //위의 기본 방법과 같이 [배경그림] 을 가지지 않고 [반투명] 으로 보여준다.
      //문자부분은 [정지점색] 으로 완전히 가리지만 나머지 행 부분은 [반투명:점] 으로
      //처리되어 배경그림이 보여진다.
      //
      //<GEditor> 에서 먼저 실험한 것을 이곳으로 옮긴것.
      //실험 내용은 <GEditor> 를 참고.
      //}----------------------------------------------------------------------------

      //[<_bmp_BreakPointLine_> 관련 처리]
      //{
          //<_bmp_> 크기가 변경된 경우, [정지점:색] 이 변경된 경우만 [다시그리기] 로
          //새로 만들어 주고, 그 외 경우는 이전에 만들어 놓은 것을 계속 사용.
          //이는 [다시그리기] 시 상당한 시간이 소요되기 때문이다.
          //}--------------------------------------------------------------------------

          if(//편집기 크기가 변경된 경우.
             (_bmp_->Width != _bmp_BreakPointLine_->Width) ||
             //[정지점행:색] 이 변경된 경우.
             (_breakline_color != _breakline_color_Save))
          {

            if(_bmp_->Width != _bmp_BreakPointLine_->Width)
            {
              //[편집기] 크기가 변경됐으므로 수반되는 크기 조정.
              _bmp_BreakPointLine_->Width       = _bmp_->Width;
              _bmp_BreakPointLine_->Height      = _line_height;

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

            }

            if(_breakline_color != _breakline_color_Save)
            {
              //현재 색을 다시 보관.
              _breakline_color_Save = _breakline_color;

            }

            //[바탕 지우기]
            //{
                _bmp_BreakPointLine_->Canvas->Brush->Color = clWhite;
                _bmp_BreakPointLine_->Canvas->FillRect(_bmp_BreakPointLine_->Canvas->ClipRect);

            //}

            //[교차 점선으로 채우기]
            //{
                //[!]{******************************************************************
                //[줄이동자:막대배경] 과 같은 [교차:점선] 으로 채운다.
                //이 부분이 처리 시간이 많이 걸리므로 한번만 처리하도록 하는 것이 핵심.
                //}*********************************************************************
                
                for(h = 0, dotStart = true; h < _bmp_BreakPointLine_->Height; h++, dotStart = !dotStart)
                {
                  for(w = 0, dot = dotStart; w <= _bmp_BreakPointLine_->Width; w++, dot = !dot)
                  {
                    if(dot == true)
                    {
                      BMP_Dot(_bmp_BreakPointLine_, w, h, _breakline_color);

                    }

                  }

                }

            //}

            //[투명 설정]
            //{
                //[!]{-----------------------------------------------------------------------
                //[교차점선] 에서 [흰색(공백)] 은 복사하지 않고 [점] 부분만 복사하도록 설정.
                //아래 <_bmp_->Canvas->Draw()> 에서 [점] 부분만 복사하게 된다.
                //}--------------------------------------------------------------------------

                _bmp_BreakPointLine_->Transparent = true;
                _bmp_BreakPointLine_->TransparentColor = clWhite;
                _bmp_BreakPointLine_->TransparentMode = tmAuto;

            //}    

          }

      //}

      //[투명:복사]
      //{
          //[!]{*************************************************************************
          //금일 새로 발견한 API 로 BitBlt() 와 속도는 비슷하나 [투명] 복사 기능이 있음.
          //위의 [투명] 속성이 적용되어 복사된다.
          //[편집기] 배경그림 위에 복사되고, 문자는 이 위에 출력되므로 [문자] 부분은
          //완전히 [정지점행:색] 으로 채워지지만 문자가 없는 행의 나머지는 [점선] 으로
          //뒤의 배경이 보이는 [반투명] 상태가 된다.
          //실험 결과 매우 보기 좋음.
          //}****************************************************************************
          
          _bmp_->Canvas->Draw(rect.Left, rect.Top, _bmp_BreakPointLine_);

      //}

  //}

}

void __fastcall Teditor_edit_Form::_BREAKPOINT_Edit_DrawAll(void)
{
  //[2007.04.15.일][생성!!!]{------------------------------------------
  //지정행이 [정지점] 이 설정된 행인 경우는 [편집기] 바탕의 행을
  //지정색으로 칠한다.
  //단, 문자열을 출력하기 전에 처리 되어야 한다.(바탕에 해당하므로...)
  //}------------------------------------------------------------------

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

  //[정지점 처리]
  //{
      //모든 [정지점] 을 일괄 처리한다.
      for(i = 0; i < _breakpoint.count; i++)
      {
        _BREAKPOINT_Edit_Draw(_breakpoint.line[i]);

      }

  //}

  return;

}

void __fastcall Teditor_edit_Form::_BREAKPOINT_Edit_Verify_Draw(int  pLINEnumber)
{
  //[2007.04.16.월][생성!!!]{--------------------------------------------------------------------
  //지정행이 [정지점] 이 있는 행인지 확인하고 [정지점] 이 있는 행인 경우만 [정지줄] 을 그려준다.
  //이 함수는 문자입력등 행단위 수정이 있는 경우 배경에 [정지줄] 을 표시하기 위하여 사용된다.
  //}--------------------------------------------------------------------------------------------

  //[정지점 확인]
  //{
      //현재 행에 [정지점] 이 설정된 행이 아니라면 처리하지 않는다.
      if(_BREAKPOINT_Search(pLINEnumber) == -1) return;

  //}

  //[정지줄 그리기]
  //{
      //지정 행 위치 배경에 [정지줄] 을 그려준다.
      _BREAKPOINT_Edit_Draw(pLINEnumber);

  //}

  return;

}

void __fastcall Teditor_edit_Form::_BREAKPOINT_Edit_StartLine_Draw(int  pLINEnumber)
{
  //[2007.04.16.월][생성!!!]{-----------------------------------------------------
  //지정행을 포함하여 지정 행 보다 큰 모든 행을 처리한다.
  //[정지점] 은 행크기 순서대로 정리된 것이 아니므로 전부 비교하여 처리해야 한다.
  //}-----------------------------------------------------------------------------

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

  //[정지줄 처리]
  //{
      for(i = 0; i < _breakpoint.count; i++)
      {
        //현재 행보다 크거나 같은 행만 처리한다.
        if(_breakpoint.line[i] >= pLINEnumber)
        {
          //[정지점] 이 있는 행인지는 아래 함수에서 자동으로 확인된다.
          _BREAKPOINT_Edit_Verify_Draw(_breakpoint.line[i]);

        }

      }

  //}

  return;

}

void __fastcall Teditor_edit_Form::_BREAKPOINT_Bmp(int  pBmpIndex)
{
  //[2009.04.29.수][생성!!!]{------------------------------------------------
  //[정지점] 을 표시할 [비트맵] 을 선택한다.
  //전용 저장공간이 있으므로 여기에 해당하는 [비트맵] 을 다시 올려주면 된다.
  //}------------------------------------------------------------------------

  switch(pBmpIndex)
  {
    case d_Editor_BreakPoint_Enable : //[정지점] 유효.
    {
      //[활성] 그림을 올려준다.(8*8)
      _bmp_breakpoint_->LoadFromFile(ExtractFilePath(Application->ExeName) + "sysbmp\\8_8\\breakpoint.bmp");

    } break;

    case d_Editor_BreakPoint_Disable : //[정지점] 무효.
    {
      //[비활성] 그림을 올려준다.(8*8)
      _bmp_breakpoint_->LoadFromFile(ExtractFilePath(Application->ExeName) + "sysbmp\\8_8\\breakpoint2.bmp");

    } break;

  }

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

  //[그림색 바꾸기]
  //{
      //그림색을 지정색으로 바꾼다.
      BMP_Self_ChangeColor2(_bmp_breakpoint_, clBlack, IDE_COLOR_breakpoint, clWhite, clWhite);

  //}

  //[다시 그리기]
  //{
      //설정되 있는 [정지점] 이 있다면 다시 그려준다.
      _DEBUG_BreakPoint();

      //다시 그려서 반영해 준다.
      _EditBuf_Text();

  //}

  return;

}

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

void __fastcall Teditor_edit_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->editorBackPicturePath;

            //[확인]
            //[
                //[2007.12.04.화][추가!!!]
                //그림이 있는지 먼저 확인한다.
                if(FileExists(_bmp_path) != true)
                {
                  //그림이 존재하지 않는 경우는 기본 그림으로 대체한다.
                  _bmp_path = IDE_BACKBMP_edit_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_, pBrightness);

  //}

  //[다시 그려서 보여주기]{----------------
  //변경 내용을 알기 위하여 다시 출력한다.
  _EditBuf_Text();
  //}--------------------------------------
           
  return;

}

void __fastcall Teditor_edit_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->edit_back_brightness);

  //[다시 그려서 보여주기]{----------------
  //변경 내용을 알기 위하여 다시 출력한다.
  _EditBuf_Text();
  //}--------------------------------------

  return;

}

//------------------------------------------------------------------------------
//[추가함수]--------------------------------------------------------------------
//------------------------------------------------------------------------------

void __fastcall Teditor_edit_Form::_Debug_BreakPoint_RePaint(void)
{
  //[2007.12.03.월][생성!!!]{----------------------------------------------
  //사용자 설정에 따라 색이 바뀌는 경우 이를 반영해주고 해당 변경 내용이
  //제대로 표시 되도록 관련 된 것을 전부 다시 그려준다.
  //이미 [편집기] 에 [정지점] 이 생성되 있는 경우 즉시 반영해 주어야 한다.
  //}----------------------------------------------------------------------

  //[VAR]
  //{
      AnsiString  bmp_path;

  //}

  //[정지점]
  //{
      //[2009.04.29.수][수정!!!]
      //{
          //현재 정지점 [유/무효] 상태에 따라 다른 기호를 사용해 주어야 한다.

          if(ide_buttons_Form->_debug_bmpbtns[d_debug_bmpbtn_breakpoint]->_index == 0)
          {
            //[활성화] 된 [정지점] 을 표시하기 위한 bmp 를 만든다.
            bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\8_8\\breakpoint.bmp";

          }
          else
          {
            //[비활성화] 기호를 사용한다.
            bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\8_8\\breakpoint2.bmp";

          }

      //}

      //그림을 올려준다.(8*8)
      _bmp_breakpoint_->LoadFromFile(bmp_path);

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

  //}

  //[정지점 줄색]
  //{
      //정지줄 색을 구한다.(테마색으로 설정하기 위한것.)
      BMP_Get_Bright_Color(IDE_COLOR_breakpoint, IDE_BRIGHT_breakline, &_breakline_color);

  //}

  //[그림색 바꾸기]
  //{
      //그림색을 지정색으로 바꾼다.
      BMP_Self_ChangeColor2(_bmp_breakpoint_, clBlack, IDE_COLOR_breakpoint, clWhite, clWhite);

  //}

  //[다시 그리기]
  //{
      //설정되 있는 [정지점] 이 있다면 다시 그려준다.
      _DEBUG_BreakPoint();

      //[편집기] 를 다시 그려 [정지점] 설정은 반영한다.
      _EditBuf_Text();

  //}

  return;

}

void __fastcall Teditor_edit_Form::_Debug_Arrow_RePaint(void)
{
  //[2007.12.03.월][생성!!!]{--------------------------------------------
  //사용자 설정에 따라 색이 바뀌는 경우 이를 반영해주고 해당 변경 내용이
  //제대로 표시 되도록 관련 된 것을 전부 다시 그려준다.
  //}--------------------------------------------------------------------

  //[VAR]
  //{
      AnsiString  bmp_path;

  //}

  //[실행 지정자]
  //{
      //[실행 지정자] 를 표시하기 위한 bmp 를 만든다.
      bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\12_12\\run_arrow.bmp";

      //그림을 올려준다.(8*8)
      _bmp_run_arrow_->LoadFromFile(bmp_path);

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

  //}

  //[그림색 바꾸기]
  //{
      //그림색을 지정색으로 바꾼다.
      BMP_Self_ChangeColor2(_bmp_run_arrow_,  clBlack, IDE_COLOR_run_arrow, clWhite, clWhite);

  //}

  //[다시 그리기]
  //{
      //다시 그려서 반영해 준다.
      _DEBUG_RunArrow(_focusLineNum, true);

  //}

  return;

}

void __fastcall Teditor_edit_Form::_CtrlAltMouse_ScrollAreaDotLine(void)
{
  //[2011.05.06.금][생성!!!]{----------------------------------------------------------
  //[Ctrl + Alt + 마우스 이동] 의 처리를 위하여 [Ctrl + Alt] 가 눌린 경우는 무조건
  //[줄이동 영역] 을 [점선] 으로 그려 준다.
  //<_mouseCtrlAlt : true> 경우가 해당된다.
  //
  //[편집기] 의 보여지는 영역을 5등분 하여 각각 영역에 따라 [줄이동 줄수] 가 변경된다.
  //
  //[1/5]       : 1줄씩 이동한다.
  //[2/5 - 4/5] : 기본 줄이동 한다.
  //[5/5]       : 1장씩 이동한다.
  //}----------------------------------------------------------------------------------

  //[영역 구분 처리]
  //{
      //[!]{------------------------------------------------------
      //<editor_edit_Form> 자체 크기가 보이는 영역의 크기가 된다.
      //}---------------------------------------------------------

      //[설정]
      //{
          _bmp_->Canvas->Pen->Color = _ide_option->color_0;
          _bmp_->Canvas->Pen->Width = 1;
          _bmp_->Canvas->Pen->Style = psDot;

      //}

      //[1줄 이동 영역(왼쪽)]
      //{
          //[!]{----------------------------
          //{1/5] 의 가장 왼쪽 영역이 된다.
          //}-------------------------------

          _bmp_->Canvas->MoveTo(this->Width/5, 1);
          _bmp_->Canvas->LineTo(this->Width/5, this->Height);

      //}


      //[기본줄 이동 영역(중간)]
      //{
          //이 영역은 사이 영역으로 다음 영역에서 표시하면 된다.

      //}

      //[1장 이동 영역(오른쪽)]
      //{
          //[!]{------------------------------
          //{5/5] 의 가장 오른쪽 영역이 된다.
          //}---------------------------------

          _bmp_->Canvas->MoveTo(this->Width - this->Width/5, 1);
          _bmp_->Canvas->LineTo(this->Width - this->Width/5, this->Height);

      //}

  //}

}

void __fastcall Teditor_edit_Form::_VLine(void)
{
  //[2012.06.08.금][생성!!!]{----------------------------------------------------
  //<Ctrl + G> 로 [세로줄] 이 설정되는 경우 이 [세로줄] 을 지정 위치에 그려준다.
  //
  //[2012.06.09.토][수정!!!]-----------------------------------------------------
  //[검증시] 에는 그리지 않는다.
  //
  //[2012.08.14.화][수정!!!]-----------------------------------------------------
  //[검증판] 영역에서는 그리지 않아야 한다.
  //}----------------------------------------------------------------------------

  //[함수 유/무효 구분]
  //{
      //[2012.06.09.토][추가!!!]{---------
      //이 함수동작이 허용된 상태만 처리.
      //}---------------------------------

      if(_sw_VLine != true) return;

  //}

  //[검증상태 인지 확인]
  //{
      //[2012.06.09.토][추가!!!]{----
      //[검증시] 에는 보이지 않는다.
      //}----------------------------

      if(ide_buttons_Form->_tabs->_tabindex > 0) return;

  //}

  //[검증판 영역인지 확인]
  //{
      //[2012.08.14.화][추가!!!]{--------
      //[검증판] 영역에는 그리지 않는다.
      //}--------------------------------

      if((_text_org_x + _vLineX) <= d_gutter_width) return;

  //}

  //[설정]
  //{
      //[2012.06.09.토][수정!!!]{-----------------------------------------------
      //[기준선] 개념으로 눈에 확 띄기 쉬운 색을 지정.
      //[환경색] 이 [검정] 색등인 경우는 [편집기] 문자와 겹쳐서 보기 좋지 않다.
      _bmp_->Canvas->Pen->Color = clRed;//_ide_option->color_0;
      //}-----------------------------------------------------------------------
      
      _bmp_->Canvas->Pen->Width = 1;
      _bmp_->Canvas->Pen->Style = psDashDotDot;

  //}

  //[1줄 이동 영역(왼쪽)]
  //{
      _bmp_->Canvas->MoveTo(_text_org_x + _vLineX, 1);
      _bmp_->Canvas->LineTo(_text_org_x + _vLineX, this->Height);

  //}

}

//------------------------------------------------------------------------------
//[찾기 대화상자 관련]----------------------------------------------------------
//------------------------------------------------------------------------------

void __fastcall Teditor_edit_Form::_FindDialog_Show(void)
{
  //[2010.06.28.월][생성!!!]{-------------------------------------------------------------------
  //현재 [선택 문자열] 이 있다면 이 문자열을 자동으로 [찾기대화상자] 에 등록해 준다.
  //
  //[2012.04.25.수][수정!!!]--------------------------------------------------------------------
  //현재 [선택영역] 이 없다면 [찾기대화상자:찾을문자열] 을 비워준다.
  //사용해 보니 이 경우는 비워주는 것이 좋다.
  //직접 착기문자열을 [붙이기] 하려는 경우 기존 문자열이 남아있어 먼저 지워야 하는 불편이 있다.
  //}-------------------------------------------------------------------------------------------

  //[VAR]
  //{
      struct CARETINFO   select_start;
      struct CARETINFO   select_end;

      //선택된 문자열을 저장하기 위한 저장소(1K 면 충분하다).
      char               select_text[1025]; //'\0' 을 위한공간 을 +1 한다.
      //'\0' 까지 포함된 크기를 가져야 한다.
      int                size;

  //}

  //[선택된 것이 있나?]
  //{
      //[!]{---------------------------------------------------
      //[선택영역] 이 있는 경우는 [선택문자열] 을 얻어야 한다.
      //}------------------------------------------------------

      if(_SELECT_Get_StartEndIndex(&select_start, &select_end) == true)
      {
        //[문자열 길이 얻기]
        //{
            //순수 문자열 길이 얻기.
            size = select_end.caret_index - select_start.caret_index;

        //[크기제한]
        //{
            //문자열은 1K 크기로 잘라낸다.
            if(size > 1024) { size = 1024; }

        //[문자열 추출]
        //{
            //[선택영역] 문자열을 추출한다.
            STR_SubString(_editbuf,
                          select_start.caret_index, size,
                          select_text);

        //}

        //[문자열안의 CR/LF 정리]
        //{
            //[!]{-----------------------------------------------
            //문자열의 CR, LF '\0' 으로 바꿔준다.
            //이는 찾기문자열은 행변환이 있으면 안되기 때문이다.
            //전용함수로 처리한다.
            //}--------------------------------------------------

            //원본을 직접 수정-----------------v
            STR_Cut_CRLF(select_text, NULL, 0, true);

        //}

        //[찾을 문자열로 등록]
        //{
            find_DialogBox_Form->_find_Edit->_EDIT_TextOut(select_text);

        //}

      }
      else
      {
        //[2012.04.25.수][추가!!!]{---------------------------
        //현재 선택된 문자열이 없다면 [찾기문자열] 을 비운다.
        //
        //[2019.01.08.화][수정!!!]----------------------------
        //선택된 문자열이 없다면 기존 문자열을 그대로 둔다.
        //이는 [형광문자] 기능을 그대로 유지하기 위한것.
        //}---------------------------------------------------

        //[2019.01.08.화][주석처리!!!]
        //find_DialogBox_Form->_find_Edit->_EDIT_TextOut("");

      }

  //}

  //[찾기대화상자 보이기]
  //{
      find_DialogBox_Form->_Show();

  //}

}

//----------------------------------------------------------------------------------------
//[검증식 바로보기 관련]------------------------------------------------------------------
//----------------------------------------------------------------------------------------

void __fastcall Teditor_edit_Form::_DbgView_Init(void)
{
  //[2011.06.20.월][생성!!!]{-----------------------
  //[선택 영역 검증식] 과 관련된 초기화를 수행한다.
  //}-----------------------------------------------

  //[VAR]
  //{
      AnsiString  bmp_path;
      int         temp;

  //}

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

      //그림 영역 크기 설정(정의된 크기를 사용한다).
      //[폭] 은 계속 동적 생성하지 않도록 화면가로 크기로 설정한다.
      _dbgView_bmp->Width       = d_dbgView_bmp_Width;
      _dbgView_bmp->Height      = d_dbgView_bmp_Height;

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

  //}

  //[글꼴 설정]
  //{
      //[2011.06.22.수][추가!!!]{---------------------------------------------------
      //[검증식] 관련은 [편집기] 와 별도의 개체이므로 별도 [글꼴] 을 사용해야 한다.
      //}---------------------------------------------------------------------------

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

      //<tree> 개체가 차지하는 공간은 비워 주어야 한다.
      _dbgView_font.margin_size     = d_dbgView_TreeArea_Width;

      _dbgView_font.offset_left     = 0;
      _dbgView_font.offset_right    = 0;
      //[2011.06.25.토][수정!!!]
      //<tree> 형태로 표시하므로 위에 1 의 여유를 준다.
      _dbgView_font.offset_top      = 1;
      _dbgView_font.offset_bottom   = 0;

      _dbgView_font.en_offset_left  = 0;
      _dbgView_font.en_offset_right = 0;

      //[행높이 구하기]
      //{
          //[2011.06.25.토][추가!!!]{------------------
          //[글꼴] 의 크기를 알기 위한 'A' 문자 출력.
          //}------------------------------------------

          FONT_Out_Moonja(_dbgView_bmp, &_dbgView_font, 0, 0, IDE_COLOR_1, IDE_COLOR_2, false, 'A', &_dbgView_EngWidth, &_dbgView_LineHeight);

      //}

  //}

  //[기본색 설정]
  //{
      //[바탕색] 은 [테마색:밝은색] 이다.
      BMP_Get_Bright_Color(_ide_option->color_0, Ide_Bright_DbgView_Back, &_dbgView_BackColor);

      //[테두리색] 은 [테마색] 자체를 사용한다.
      _dbgView_BorderColor = clBlack;// _ide_option->color_0;

      //문자색은 기본색으로 설정.
      _dbgView_FontColor = clWhite;// IDE_COLOR_1;

      //흰색과 겹치지 않도록 이 색의 <-1> 값으로 처리한다.
      _dbgView_TransColor = clWhite-1;

  //}

  _dbgView_Width  = 0;
  _dbgView_Height = 0;

  _dbgViewDspInfo.displayStr[0] = '\0';
  //[2011.07.01.금][추가!!!]
  //기본은 16진수 보기다.
  //[2011.07.21.목][수정!!!]
  //[정의이름] 으로 변경한다.
  _dbgViewDspInfo.viewKind = Opt_Ide_DbgExpView_Mode;

  //[2011.06.30.목][추가!!!]{--------
  DebugViewInfo_Init(&_dbgViewInfo);
  //}--------------------------------

  //기본 상태는 [열기전] 상태가 된다.
  _dbgView_State = '+';

  //[2011.06.23.목][추가!!!]
  _dbgView_X = 0;
  _dbgView_Y = 0;

  //검증시에만 유효하다.
  _dbgView_Enable = false;

  //처음에는 보이지 않는다.
  _dbgView_Visible = false;

  //처음에는 [기본보기] 로 시작한다.
  _dbgView_FixView = false;

  //[<Tree>엄지그림 올리기]
  //{
      //[2011.06.25.토][추가!!!]{----------------------------------
      //[검증식 보기판] 에 사용할 [<Tree> 엄지그림] 을 읽어들인다.
      //원래 색 그대로 사용하므로 별도의 처리를 할 필요는 없다.
      //}----------------------------------------------------------

      //[tree-p]
      bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\tree\\tree_p.bmp";
      _Bmp_Create_And_Load(&_bmp_tree_p, bmp_path);

      //[tree-m]
      bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\tree\\tree_m.bmp";
      _Bmp_Create_And_Load(&_bmp_tree_m, bmp_path);

      //[tree-i]
      bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\tree\\tree_i.bmp";
      _Bmp_Create_And_Load(&_bmp_tree_i, bmp_path);

      //[tree-3]
      bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\tree\\tree_3.bmp";
      _Bmp_Create_And_Load(&_bmp_tree_3, bmp_path);

      //[tree-end]
      bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\tree\\tree_end.bmp";
      _Bmp_Create_And_Load(&_bmp_tree_end, bmp_path);

      //[tree-x]
      bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\tree\\tree_x.bmp";
      _Bmp_Create_And_Load(&_bmp_tree_x, bmp_path);

  //}

  //[검증식 보기판 닫기 버튼]
  //{
      //[2011.06.26.일][추가!!!]
      bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\11_11\\close_x.bmp";
      _Bmp_Create_And_Load(&_dbgView_bmp_Close, bmp_path);

      _dbgView_bmp_Close_Down = false;

  //}

  //[검증식 위치로 이동 버튼]
  //{
      //[2011.06.27.월][추가!!!]
      bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\11_11\\item.bmp";
      _Bmp_Create_And_Load(&_dbgView_bmp_GoBlock, bmp_path);

      _dbgView_bmp_GoBlock_Down = false;

  //}

  //[검증식 추가 버튼]
  //{
      //[2011.07.10.일][추가!!!]{-------------------
      //[검증식 추가 버튼] 관련 기능을 초기화 한다.
      //}-------------------------------------------

      //[기본판]
      //{
          //실제 그림 영역을 생성한다.
          _dbgView_bmp_AddBtn = new Graphics::TBitmap;

          //17*17 의 크기면 충분한다(고정크기).
          _dbgView_bmp_AddBtn->Width  = 17;
          _dbgView_bmp_AddBtn->Height = 17;

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

      //}

      //[검증식 위치로 이동 버튼]
      //{
          bmp_path = ExtractFilePath(Application->ExeName) + "sysbmp\\13_13\\add.bmp";
          _Bmp_Create_And_Load(&_dbgView_bmp_AddBtn_icon, bmp_path);

      //}

      //처음에는 눌리지 않은 것이다.
      _dbgView_bmp_AddBtn_Down = false;

  //}

}

void __fastcall Teditor_edit_Form::_DbgView_Shape(void)
{
  //[2011.06.20.월][생성!!!]{-------------------------------------------------
  //실제 [편집기] 에 표시할 그림을 만들어 주는 역활을 한다.
  //표시할 자료는 전체가 4개 행 문자열이므로 아예 전체 문자열을
  //[검증식] 자체를 처리해 주는 <debug_view.cpp> 에서 만들어 주고
  //여기서는 이 문자열을 전달받아 [행단위] 로 추출하여 각 항목을 처리해 준다.
  //
  //[2011.06.26.일][추가!!!]--------------------------------------------------
  //[닫기] 버튼을 추가한다.
  //}-------------------------------------------------------------------------

  //[VAR]
  //{
      int   color;

      int   strAreaWidth, strAreaHeight;

      int   i, x, y;

      //[2011.06.28.화][추가!!!]
      char  tempStr[Opt_DebugView_StrBufSize];

  //}

  //[유효한가?]
  //{
      //[!]{-----------------------------------------------------
      //[선택 영역 검증식] 은 [개발검증] 상태인 경우만 유효하다.
      //}--------------------------------------------------------

      if(!((_dbgView_Enable == true) &&
           //[2011.06.30.목][추가!!!
           //반드시 <*.c> 문서의 경우만 처리해야 한다.
           (_fileKind == d_Editor_FileKind_c))) return;

  //}

  //[<기본보기/고정보기> 구분 처리]
  //{
      //[2011.06.26.일][추가!!!]{----------------------
      //[기본보기/고정보기] 를 구분한다.
      if(_dbgView_FixView == true) { goto lbFixView; }
      else                         { goto lbDefault; }
      //}----------------------------------------------

      lbDefault:

      //[상태에 다른 처리]
      //{
          //[2011.06.25.토][수정!!!]{-------------------
          //<+>, <->, <x> 등 상태에 따라 개별 처리한다.
          //}-------------------------------------------

          switch(_dbgView_State)
          {
            case '+' :
            {
              //[글꼴 설정]
              //{
                  //[2011.06.26.일][추가!!!]
                  _dbgView_font.margin_size = d_dbgView_TreeArea_Width2;

              //}

              //[문자열 설정]
              //{
                  STR_Assign(_dbgViewDspInfo.displayStr,
                             "검증식 계산");

              //}

              //[문자열 출력 영역 크기 계산]
              //{
                  FONT_Get_StringOutAreaInfo(&_dbgView_font, d_FONTSTYLE_default,
                                             _dbgViewDspInfo.displayStr,
                                             &strAreaWidth, &strAreaHeight);

              //}

              //[실제 그림 영역 계산]
              //{
                  //[!]{------------------------------------------------------------------------------
                  //실제 그림이 그려지는 영역을 구한다.
                  //이는 문자열이 출력되는 영역의 크기와 관련있으므로 반드시 이 위치에서 구해야 한다.
                  //}---------------------------------------------------------------------------------

                  _dbgView_Width  = 2 + d_dbgView_TreeArea_Width2 + strAreaWidth + 2 + _dbgView_bmp_Close->Width + 2;

                  _dbgView_Height = 2 + strAreaHeight + 2;

              //}

              //[바탕색]
              //{
                  //바탕을 일단 배경색으로 지운다.
                  _dbgView_bmp->Canvas->Brush->Color = _dbgView_BackColor;
                  _dbgView_bmp->Canvas->FillRect(_dbgView_bmp->Canvas->ClipRect);

              //}

              //[<tree> 모양 내기]
              //{
                  //[!]{------------------------
                  //<[+]> 기호만 그려주면 된다.
                  //}---------------------------

                  //<[+]> [엄지그림] 을 표시한다.
                  BMP_Copy_Transparent(_bmp_tree_p, 0, 0, _bmp_tree_p->Width, _bmp_tree_p->Height,
                                       _dbgView_bmp, 3, 4, 9, 9,
                                       -1);

              //}

              //[내용 출력]
              //{
                  FONT_Out_StyleString2(_dbgView_bmp, &_dbgView_font, 0, 2,
                                        _dbgView_FontColor, _dbgView_BackColor, true, d_FONTSTYLE_default,
                                        _dbgViewDspInfo.displayStr,
                                        d_FONT_underline_no, true, 0, _dbgView_FontColor,
                                        &strAreaWidth, &strAreaHeight);

              //}

              //[닫기 버튼]
              //{
                  //[2011.06.26.일][추가!!!]{-----------
                  //[닫기] 버튼을 맨 오른쪽에 그려준다.
                  //}-----------------------------------

                  //[영역정보]
                  //{
                      //[2011.06.29.수][추가!!!]
                      _dbgView_bmp_Close_TRect.Left   = _dbgView_Width - _dbgView_bmp_Close->Width - 3;
                      _dbgView_bmp_Close_TRect.Top    = 3;
                      _dbgView_bmp_Close_TRect.Right  = _dbgView_bmp_Close_TRect.Left + 11;
                      _dbgView_bmp_Close_TRect.Bottom = _dbgView_bmp_Close_TRect.Top + 11;

                  //}

                  BMP_Copy_Transparent(_dbgView_bmp_Close, 0, 0, _dbgView_bmp_Close->Width, _dbgView_bmp_Close->Height,
                                       _dbgView_bmp,
                                       _dbgView_bmp_Close_TRect.Left, _dbgView_bmp_Close_TRect.Top,
                                       _dbgView_bmp_Close_TRect.Width(), _dbgView_bmp_Close_TRect.Height(),
                                       -1);

              //}

              //[테두리]
              //{
                  _dbgView_bmp->Canvas->Pen->Color   = _dbgView_BorderColor;
                  _dbgView_bmp->Canvas->Pen->Width   = 1;
                  _dbgView_bmp->Canvas->Brush->Style = bsClear;
                  _dbgView_bmp->Canvas->Rectangle(0, 0, _dbgView_Width, _dbgView_Height);

              //}

              //[검증식 추가 버튼]
              //{
                  //[2011.07.10.일][추가!!!]{---------------------------------------------------
                  //원래 한번만 그려주면 되는 것이지만 개념상 [검증식 보기판] 의 <+> 상태에서만
                  //보여지는 것이므로 같이 그려준다.
                  //}---------------------------------------------------------------------------
                  
                  _DbgView_AddBtn_Shape();

              //}

            } break;

            case '-' :
            {
              //[글꼴 설정]
              //{
                  //[2011.06.26.일][추가!!!]
                  _dbgView_font.margin_size = d_dbgView_TreeArea_Width;

              //}

              //[문자열 출력 영역 크기 계산]
              //{
                  FONT_Get_StringOutAreaInfo(&_dbgView_font, d_FONTSTYLE_default,
                                             _dbgViewDspInfo.displayStr,
                                             &strAreaWidth, &strAreaHeight);

              //}

              //[실제 그림 영역 계산]
              //{
                  //[!]{------------------------------------------------------------------------------
                  //실제 그림이 그려지는 영역을 구한다.
                  //이는 문자열이 출력되는 영역의 크기와 관련있으므로 반드시 이 위치에서 구해야 한다.
                  //}---------------------------------------------------------------------------------

                  _dbgView_Width  = 2 + d_dbgView_TreeArea_Width + strAreaWidth + 2 + _dbgView_bmp_Close->Width + 2;

                  _dbgView_Height = 2 + strAreaHeight + 2;

              //}

              //[바탕색]
              //{
                  //바탕을 일단 배경색으로 지운다.
                  _dbgView_bmp->Canvas->Brush->Color = _dbgView_BackColor;
                  _dbgView_bmp->Canvas->FillRect(_dbgView_bmp->Canvas->ClipRect);

              //}

              //[<tree> 모양 내기]
              //{
                  //[세로 줄기 그리기]
                  //{
                      //[!]{-----------------------------------------------------------
                      //세로 줄기를 먼저 그린다.
                      //<[-]> 를 제외하고는 선으로만 돼 있으므로 [줄기] 를 먼저 그리고
                      //이 위치에 [엄지그림] 을 출력해도 무관하다.
                      //}--------------------------------------------------------------

                      _dbgView_bmp->Canvas->Pen->Style   = psSolid;
                      _dbgView_bmp->Canvas->Pen->Color   = clBlack;
                      _dbgView_bmp->Canvas->Pen->Width   = 1;

                      _dbgView_bmp->Canvas->MoveTo(3 + 4, 3 + 9);
                      _dbgView_bmp->Canvas->LineTo(3 + 4, 3 + 10 + _dbgView_LineHeight*2 + 4);

                  //}

                  //<[-]> [엄지그림] 을 표시한다.
                  x = 3; y = 4;
                  BMP_Copy_Transparent(_bmp_tree_m, 0, 0, _bmp_tree_m->Width, _bmp_tree_m->Height,
                                       _dbgView_bmp, x, y, 9, 9,
                                       -1);

                  y += _dbgView_LineHeight;
                  BMP_Copy_Transparent(_bmp_tree_3, 0, 0, _bmp_tree_3->Width, _bmp_tree_3->Height,
                                       _dbgView_bmp, x, y, 9, 9,
                                       clWhite);

                  y += _dbgView_LineHeight;
                  BMP_Copy_Transparent(_bmp_tree_3, 0, 0, _bmp_tree_3->Width, _bmp_tree_3->Height,
                                       _dbgView_bmp, x, y, 9, 9,
                                       clWhite);

                  y += _dbgView_LineHeight;
                  BMP_Copy_Transparent(_bmp_tree_end, 0, 0, _bmp_tree_end->Width, _bmp_tree_end->Height,
                                       _dbgView_bmp, x, y, 9, 9,
                                       clWhite);

                  for(i = 0, x = 3 + 9, y = 4; i < 4; i++, y += _dbgView_LineHeight)
                  {
                    BMP_Copy_Transparent(_bmp_tree_i, 0, 0, _bmp_tree_i->Width, _bmp_tree_i->Height,
                                         _dbgView_bmp, x, y, 9, 9,
                                         clWhite);

                  }

              //}

              //[내용 출력]
              //{
                  FONT_Out_StyleString2(_dbgView_bmp, &_dbgView_font, 0, 2,
                                        _dbgView_FontColor, _dbgView_BackColor, true, d_FONTSTYLE_default,
                                        _dbgViewDspInfo.displayStr,
                                        d_FONT_underline_no, true, 0, _dbgView_FontColor,
                                        &strAreaWidth, &strAreaHeight);

              //}

              //[닫기 버튼]
              //{
                  //[2011.06.26.일][추가!!!]{-----------
                  //[닫기] 버튼을 맨 오른쪽에 그려준다.
                  //}-----------------------------------

                  //[영역정보]
                  //{
                      //[2011.06.29.수][추가!!!]
                      _dbgView_bmp_Close_TRect.Left   = _dbgView_Width - _dbgView_bmp_Close->Width - 3;
                      _dbgView_bmp_Close_TRect.Top    = 3;
                      _dbgView_bmp_Close_TRect.Right  = _dbgView_bmp_Close_TRect.Left + 11;
                      _dbgView_bmp_Close_TRect.Bottom = _dbgView_bmp_Close_TRect.Top + 11;

                  //}

                  BMP_Copy_Transparent(_dbgView_bmp_Close, 0, 0, _dbgView_bmp_Close->Width, _dbgView_bmp_Close->Height,
                                       _dbgView_bmp,
                                       _dbgView_bmp_Close_TRect.Left, _dbgView_bmp_Close_TRect.Top,
                                       _dbgView_bmp_Close_TRect.Width(), _dbgView_bmp_Close_TRect.Height(),
                                       -1);

              //}

              //[테두리]
              //{
                  _dbgView_bmp->Canvas->Pen->Color   = _dbgView_BorderColor;
                  _dbgView_bmp->Canvas->Pen->Width   = 1;
                  _dbgView_bmp->Canvas->Brush->Style = bsClear;
                  _dbgView_bmp->Canvas->Rectangle(0, 0, _dbgView_Width, _dbgView_Height);

              //}

              //[모서리 만들기]
              //{
                  //[201.06.24.금][추가!!!]{---------------------------------
                  //왼쪽 아래 모서리를 만든다.
                  //[흰색] 을 복사하지 않으므로 이 색으로 모서리를 칠해준다.
                  //}--------------------------------------------------------

                  //[2011.06.25.토][수정!!!]{--------------------------------
                  //9 가 왼쪽 아래 모서리 와 잘 어울리는 가장 적합한 값이다.
                  //}--------------------------------------------------------

                  _dbgView_EdgeSize = 9;

                  for(y = (_dbgView_Height - _dbgView_EdgeSize - 1), i = 1;
                      y <= _dbgView_Height;
                      y++, i++)
                  {
                    for(x = 0; x < i; x++)
                    {
                      BMP_Dot(_dbgView_bmp, x, y, _dbgView_TransColor);

                    }

                  }

                  //[모서리 테두리]
                  //{
                      for(y = (_dbgView_Height - _dbgView_EdgeSize - 1), x = 0;
                          y <= _dbgView_Height;
                          y++, x++)
                      {
                        BMP_Dot(_dbgView_bmp, x, y, _dbgView_BorderColor);

                      }

                  //}

              //}

            } break;

            case 'x' :
            {
              //[글꼴 설정]
              //{
                  //[2011.06.26.일][추가!!!]
                  _dbgView_font.margin_size = d_dbgView_TreeArea_Width2;

              //}

              //[문자열 설정]
              //{
                  STR_Assign(_dbgViewDspInfo.displayStr,
                             "계산할수 없는 검증식");

              //}

              //[문자열 출력 영역 크기 계산]
              //{
                  FONT_Get_StringOutAreaInfo(&_dbgView_font, d_FONTSTYLE_default,
                                             _dbgViewDspInfo.displayStr,
                                             &strAreaWidth, &strAreaHeight);

              //}

              //[실제 그림 영역 계산]
              //{
                  //[!]{------------------------------------------------------------------------------
                  //실제 그림이 그려지는 영역을 구한다.
                  //이는 문자열이 출력되는 영역의 크기와 관련있으므로 반드시 이 위치에서 구해야 한다.
                  //}---------------------------------------------------------------------------------

                  _dbgView_Width  = 2 + d_dbgView_TreeArea_Width2 + strAreaWidth + 2 + _dbgView_bmp_Close->Width + 2;

                  _dbgView_Height = 2 + strAreaHeight + 2;

              //}

              //[바탕색]
              //{
                  //바탕을 [적색] 으로 만들어 [오류] 임을 강력하게 알려준다.
                  _dbgView_bmp->Canvas->Brush->Color = clRed;//_dbgView_BackColor;
                  _dbgView_bmp->Canvas->FillRect(_dbgView_bmp->Canvas->ClipRect);

              //}

              //[<tree> 모양 내기]
              //{
                  //[!]{------------------------
                  //<[x]> 기호만 그려주면 된다.
                  //}---------------------------

                  //<[x]> [엄지그림] 을 표시한다.
                  BMP_Copy_Transparent(_bmp_tree_x, 0, 0, _bmp_tree_x->Width, _bmp_tree_x->Height,
                                       _dbgView_bmp, 3, 4, 9, 9,
                                       -1);

              //}

              //[내용 출력]
              //{
                  FONT_Out_StyleString2(_dbgView_bmp, &_dbgView_font, 0, 2,
                                        _dbgView_FontColor, _dbgView_BackColor, true, d_FONTSTYLE_default,
                                        _dbgViewDspInfo.displayStr,
                                        d_FONT_underline_no, true, 0, _dbgView_FontColor,
                                        &strAreaWidth, &strAreaHeight);

              //}

              //[닫기 버튼]
              //{
                  //[2011.06.26.일][추가!!!]{-----------
                  //[닫기] 버튼을 맨 오른쪽에 그려준다.
                  //}-----------------------------------

                  //[영역정보]
                  //{
                      //[2011.06.29.수][추가!!!]
                      _dbgView_bmp_Close_TRect.Left   = _dbgView_Width - _dbgView_bmp_Close->Width - 3;
                      _dbgView_bmp_Close_TRect.Top    = 3;
                      _dbgView_bmp_Close_TRect.Right  = _dbgView_bmp_Close_TRect.Left + 11;
                      _dbgView_bmp_Close_TRect.Bottom = _dbgView_bmp_Close_TRect.Top + 11;

                  //}

                  BMP_Copy_Transparent(_dbgView_bmp_Close, 0, 0, _dbgView_bmp_Close->Width, _dbgView_bmp_Close->Height,
                                       _dbgView_bmp,
                                       _dbgView_bmp_Close_TRect.Left, _dbgView_bmp_Close_TRect.Top,
                                       _dbgView_bmp_Close_TRect.Width(), _dbgView_bmp_Close_TRect.Height(),
                                       -1);

              //}

              //[테두리]
              //{
                  _dbgView_bmp->Canvas->Pen->Color   = _dbgView_BorderColor;
                  _dbgView_bmp->Canvas->Pen->Width   = 1;
                  _dbgView_bmp->Canvas->Brush->Style = bsClear;
                  _dbgView_bmp->Canvas->Rectangle(0, 0, _dbgView_Width, _dbgView_Height);

              //}

            } break;

          }

          //[2011.06.26.일][추가!!!]
          //[기본보기] 처리가 끝났으므로 여기서 종료한다.
          goto lbDraw;

      //}

      lbFixView:

      //[상태에 다른 처리]
      //{
          //[2011.06.26.일][추가!!!]{-----------------------
          //[고정보기] 인 경우를 처리한다.
          //이 경우는 [편집기] 위에 고정으로 보여지게 된다.
          //}-----------------------------------------------

          switch(_dbgView_State)
          {
            case '+' :
            {
              //[글꼴 설정]
              //{
                  //[2011.06.26.일][추가!!!]
                  _dbgView_font.margin_size = d_dbgView_TreeArea_Width2;

              //}

              //[문자열 설정]
              //{
                  STR_Assign(_dbgViewDspInfo.displayStr,
                             "검증식 계산");

              //}

              //[문자열 출력 영역 크기 계산]
              //{
                  FONT_Get_StringOutAreaInfo(&_dbgView_font, d_FONTSTYLE_default,
                                             _dbgViewDspInfo.displayStr,
                                             &strAreaWidth, &strAreaHeight);

              //}

              //[실제 그림 영역 계산]
              //{
                  //[!]{------------------------------------------------------------------------------
                  //실제 그림이 그려지는 영역을 구한다.
                  //[고정보기] 의 경우는 현재 보이는 [편집기] 영역의 폭과 같아야 한다.
                  //}---------------------------------------------------------------------------------

                  _dbgView_Width  = this->Width - d_gutter_width - ide_editor_Form->_scroll_v_Form->Width;

                  _dbgView_Height = 2 + strAreaHeight + 2;

              //}

              //[바탕색]
              //{
                  //바탕을 일단 배경색으로 지운다.
                  _dbgView_bmp->Canvas->Brush->Color = _dbgView_BackColor;
                  _dbgView_bmp->Canvas->FillRect(_dbgView_bmp->Canvas->ClipRect);

              //}

              //[<tree> 모양 내기]
              //{
                  //[!]{------------------------
                  //<[+]> 기호만 그려주면 된다.
                  //}---------------------------

                  //<[+]> [엄지그림] 을 표시한다.
                  BMP_Copy_Transparent(_bmp_tree_p, 0, 0, _bmp_tree_p->Width, _bmp_tree_p->Height,
                                       _dbgView_bmp, 3, 4, 9, 9,
                                       -1);

              //}

              //[내용 출력]
              //{
                  FONT_Out_StyleString2(_dbgView_bmp, &_dbgView_font, 0, 2,
                                        _dbgView_FontColor, _dbgView_BackColor, true, d_FONTSTYLE_default,
                                        _dbgViewDspInfo.displayStr,
                                        d_FONT_underline_no, true, 0, _dbgView_FontColor,
                                        &strAreaWidth, &strAreaHeight);

              //}

              //[닫기 버튼]
              //{
                  //[2011.06.26.일][추가!!!]{-----------
                  //[닫기] 버튼을 맨 오른쪽에 그려준다.
                  //}-----------------------------------

                  //[영역정보]
                  //{
                      //[2011.06.29.수][추가!!!]
                      _dbgView_bmp_Close_TRect.Left   = _dbgView_Width - _dbgView_bmp_Close->Width - 3;
                      _dbgView_bmp_Close_TRect.Top    = 3;
                      _dbgView_bmp_Close_TRect.Right  = _dbgView_bmp_Close_TRect.Left + 11;
                      _dbgView_bmp_Close_TRect.Bottom = _dbgView_bmp_Close_TRect.Top + 11;

                  //}

                  BMP_Copy_Transparent(_dbgView_bmp_Close, 0, 0, _dbgView_bmp_Close->Width, _dbgView_bmp_Close->Height,
                                       _dbgView_bmp,
                                       _dbgView_bmp_Close_TRect.Left, _dbgView_bmp_Close_TRect.Top,
                                       _dbgView_bmp_Close_TRect.Width(), _dbgView_bmp_Close_TRect.Height(),
                                       -1);

              //}

              //[검증식으로 이동]
              //{
                  //[2011.06.27.월][추가!!!]{-----------------------------
                  //[검증식으로 이동] 버튼을 [닫기] 버튼 안쪽에 올려준다.
                  //}-----------------------------------------------------

                  //[영역정보]
                  //{
                      //[2011.06.29.수][추가!!!]
                      _dbgView_bmp_GoBlock_TRect.Left   = _dbgView_Width - _dbgView_bmp_Close->Width - 3 - _dbgView_bmp_GoBlock->Width - 3;
                      _dbgView_bmp_GoBlock_TRect.Top    = 3;
                      _dbgView_bmp_GoBlock_TRect.Right  = _dbgView_bmp_GoBlock_TRect.Left + 11;
                      _dbgView_bmp_GoBlock_TRect.Bottom = _dbgView_bmp_GoBlock_TRect.Top + 11;

                  //}

                  BMP_Copy_Transparent(_dbgView_bmp_GoBlock, 0, 0, _dbgView_bmp_GoBlock->Width, _dbgView_bmp_GoBlock->Height,
                                       _dbgView_bmp,
                                       _dbgView_bmp_GoBlock_TRect.Left, _dbgView_bmp_GoBlock_TRect.Top,
                                       _dbgView_bmp_GoBlock_TRect.Width(), _dbgView_bmp_GoBlock_TRect.Height(),
                                       clWhite);

              //}

              //[테두리]
              //{
                  _dbgView_bmp->Canvas->Pen->Color   = _dbgView_BorderColor;
                  _dbgView_bmp->Canvas->Pen->Width   = 1;
                  _dbgView_bmp->Canvas->Brush->Style = bsClear;
                  _dbgView_bmp->Canvas->Rectangle(0, 0, _dbgView_Width, _dbgView_Height);

              //}

            } break;

            case '-' :
            {
              //[글꼴 설정]
              //{
                  //[2011.06.26.일][추가!!!]
                  _dbgView_font.margin_size = d_dbgView_TreeArea_Width;

              //}

              //[문자열 출력 영역 크기 계산]
              //{
                  FONT_Get_StringOutAreaInfo(&_dbgView_font, d_FONTSTYLE_default,
                                             _dbgViewDspInfo.displayStr,
                                             &strAreaWidth, &strAreaHeight);

              //}

              //[실제 그림 영역 계산]
              //{
                  //[!]{------------------------------------------------------------------------------
                  //실제 그림이 그려지는 영역을 구한다.
                  //이는 문자열이 출력되는 영역의 크기와 관련있으므로 반드시 이 위치에서 구해야 한다.
                  //}---------------------------------------------------------------------------------

                  _dbgView_Width  = this->Width - d_gutter_width - ide_editor_Form->_scroll_v_Form->Width;

                  _dbgView_Height = 2 + strAreaHeight + 2 +
                                    //[2011.06.28.화][추가!!!]
                                    //가장 위에 [검증식 문자열] 이 추가된다.
                                    _dbgView_LineHeight + 3 + 1;

              //}

              //[바탕색]
              //{
                  //바탕을 일단 배경색으로 지운다.
                  _dbgView_bmp->Canvas->Brush->Color = _dbgView_BackColor;
                  _dbgView_bmp->Canvas->FillRect(_dbgView_bmp->Canvas->ClipRect);

              //}

              //[<tree> 모양 내기]
              //{
                  //[세로 줄기 그리기]
                  //{
                      //[!]{-----------------------------------------------------------
                      //세로 줄기를 먼저 그린다.
                      //<[-]> 를 제외하고는 선으로만 돼 있으므로 [줄기] 를 먼저 그리고
                      //이 위치에 [엄지그림] 을 출력해도 무관하다.
                      //}--------------------------------------------------------------

                      _dbgView_bmp->Canvas->Pen->Style   = psSolid;
                      _dbgView_bmp->Canvas->Pen->Color   = clBlack;
                      _dbgView_bmp->Canvas->Pen->Width   = 1;

                      _dbgView_bmp->Canvas->MoveTo(3 + 4, 3 + 9 + _dbgView_LineHeight + 4);
                      _dbgView_bmp->Canvas->LineTo(3 + 4, 3 + 10 + _dbgView_LineHeight*2 + 4 + _dbgView_LineHeight + 4);

                  //}

                  //<[-]> [엄지그림] 을 표시한다.
                  x = 3; y = 4 + _dbgView_LineHeight + 4;
                  BMP_Copy_Transparent(_bmp_tree_m, 0, 0, _bmp_tree_m->Width, _bmp_tree_m->Height,
                                       _dbgView_bmp, x, y, 9, 9,
                                       -1);

                  y += _dbgView_LineHeight;
                  BMP_Copy_Transparent(_bmp_tree_3, 0, 0, _bmp_tree_3->Width, _bmp_tree_3->Height,
                                       _dbgView_bmp, x, y, 9, 9,
                                       clWhite);

                  y += _dbgView_LineHeight;
                  BMP_Copy_Transparent(_bmp_tree_3, 0, 0, _bmp_tree_3->Width, _bmp_tree_3->Height,
                                       _dbgView_bmp, x, y, 9, 9,
                                       clWhite);

                  y += _dbgView_LineHeight;
                  BMP_Copy_Transparent(_bmp_tree_end, 0, 0, _bmp_tree_end->Width, _bmp_tree_end->Height,
                                       _dbgView_bmp, x, y, 9, 9,
                                       clWhite);

                  for(i = 0, x = 3 + 9, y = 4 + _dbgView_LineHeight + 4; i < 4; i++, y += _dbgView_LineHeight)
                  {
                    BMP_Copy_Transparent(_bmp_tree_i, 0, 0, _bmp_tree_i->Width, _bmp_tree_i->Height,
                                         _dbgView_bmp, x, y, 9, 9,
                                         clWhite);

                  }

              //}

              //[검증식 문자열 출력]
              //{
                  //[2011.06.28.화][추가!!!]{-------------------
                  //[검증식 문자열] 은 항상 가장 위에 출력한다.
                  //}-------------------------------------------

                  //[2012.03.30.금][수정!!!]{--------------------------------------------------------
                  //[말줄임] 관련 가장 기본 함수인 <font.cpp:Font_LineStr_Get_Length_condWidth()> 가
                  //보다 정확하게 수정되어 관련 모든 함수를 사용한 부분은 다 수정한다.
                  //}--------------------------------------------------------------------------------
                  //-------------------------------------------v
                  _DbgView_MakeDspExpStr(_dbgView_Width - 42 + 8, tempStr);

                  //기준 위치에 출력한다.
                  _dbgView_font.margin_size = 2;

                  FONT_Out_StyleString2(_dbgView_bmp, &_dbgView_font, 0, 2,
                                        _dbgView_FontColor, _dbgView_BackColor, true, d_FONTSTYLE_default,
                                        //clBlack, _dbgView_BackColor, true, d_FONTSTYLE_default,
                                        tempStr,
                                        d_FONT_underline_no, true, 0, _dbgView_FontColor,
                                        &strAreaWidth, &strAreaHeight);

                  //[분리 점선]
                  //{
                      BMP_Get_Bright_Color(_ide_option->color_0, 200/*255 - Ide_Bright_DbgView_Back*/, &color);

                      _dbgView_bmp->Canvas->Pen->Color = color;//clWhite;//_ide_option->color_0;
                      _dbgView_bmp->Canvas->Pen->Width = 1;
                      _dbgView_bmp->Canvas->Pen->Style = psDot;

                      _dbgView_bmp->Canvas->MoveTo(0, _dbgView_LineHeight + 4);
                      _dbgView_bmp->Canvas->LineTo(this->Width, _dbgView_LineHeight + 4);

                      _dbgView_bmp->Canvas->Pen->Style = psSolid;

                  //}

              //}

              //[내용 출력]
              //{
                  //[2011.06.28.화][추가!!!]
                  //위에서 [검증식 문자열 출력] 시 위치가 변경되므로 다시 조정해 준다.
                  _dbgView_font.margin_size = d_dbgView_TreeArea_Width;

                  FONT_Out_StyleString2(_dbgView_bmp, &_dbgView_font, 0, 2 + _dbgView_LineHeight + 4,
                                        _dbgView_FontColor, _dbgView_BackColor, true, d_FONTSTYLE_default,
                                        _dbgViewDspInfo.displayStr,
                                        d_FONT_underline_no, true, 0, _dbgView_FontColor,
                                        &strAreaWidth, &strAreaHeight);

              //}

              //[닫기 버튼]
              //{
                  //[2011.06.26.일][추가!!!]{-----------
                  //[닫기] 버튼을 맨 오른쪽에 그려준다.
                  //}-----------------------------------

                  //[영역정보]
                  //{
                      //[2011.06.29.수][추가!!!]
                      _dbgView_bmp_Close_TRect.Left   = _dbgView_Width - _dbgView_bmp_Close->Width - 3;
                      _dbgView_bmp_Close_TRect.Top    = 3;
                      _dbgView_bmp_Close_TRect.Right  = _dbgView_bmp_Close_TRect.Left + 11;
                      _dbgView_bmp_Close_TRect.Bottom = _dbgView_bmp_Close_TRect.Top + 11;

                  //}

                  BMP_Copy_Transparent(_dbgView_bmp_Close, 0, 0, _dbgView_bmp_Close->Width, _dbgView_bmp_Close->Height,
                                       _dbgView_bmp,
                                       _dbgView_bmp_Close_TRect.Left, _dbgView_bmp_Close_TRect.Top,
                                       _dbgView_bmp_Close_TRect.Width(), _dbgView_bmp_Close_TRect.Height(),
                                       -1);

              //}

              //[검증식으로 이동]
              //{
                  //[2011.06.27.월][추가!!!]{-----------------------------
                  //[검증식으로 이동] 버튼을 [닫기] 버튼 안쪽에 올려준다.
                  //}-----------------------------------------------------

                  //[영역정보]
                  //{
                      //[2011.06.29.수][추가!!!]
                      _dbgView_bmp_GoBlock_TRect.Left   = _dbgView_Width - _dbgView_bmp_Close->Width - 3 - _dbgView_bmp_GoBlock->Width - 3;
                      _dbgView_bmp_GoBlock_TRect.Top    = 3;
                      _dbgView_bmp_GoBlock_TRect.Right  = _dbgView_bmp_GoBlock_TRect.Left + 11;
                      _dbgView_bmp_GoBlock_TRect.Bottom = _dbgView_bmp_GoBlock_TRect.Top + 11;

                  //}

                  BMP_Copy_Transparent(_dbgView_bmp_GoBlock, 0, 0, _dbgView_bmp_GoBlock->Width, _dbgView_bmp_GoBlock->Height,
                                       _dbgView_bmp,
                                       _dbgView_bmp_GoBlock_TRect.Left, _dbgView_bmp_GoBlock_TRect.Top,
                                       _dbgView_bmp_GoBlock_TRect.Width(), _dbgView_bmp_GoBlock_TRect.Height(),
                                       clWhite);

              //}

              //[테두리]
              //{
                  _dbgView_bmp->Canvas->Pen->Color   = _dbgView_BorderColor;
                  _dbgView_bmp->Canvas->Pen->Width   = 1;
                  _dbgView_bmp->Canvas->Brush->Style = bsClear;
                  _dbgView_bmp->Canvas->Rectangle(0, 0, _dbgView_Width, _dbgView_Height);

              //}

            } break;

            case 'x' :
            {
              //[글꼴 설정]
              //{
                  //[2011.06.26.일][추가!!!]
                  _dbgView_font.margin_size = d_dbgView_TreeArea_Width2;

              //}

              //[문자열 설정]
              //{
                  STR_Assign(_dbgViewDspInfo.displayStr,
                             "계산할수 없는 검증식");

              //}

              //[문자열 출력 영역 크기 계산]
              //{
                  FONT_Get_StringOutAreaInfo(&_dbgView_font, d_FONTSTYLE_default,
                                             _dbgViewDspInfo.displayStr,
                                             &strAreaWidth, &strAreaHeight);

              //}

              //[실제 그림 영역 계산]
              //{
                  //[!]{------------------------------------------------------------------------------
                  //실제 그림이 그려지는 영역을 구한다.
                  //이는 문자열이 출력되는 영역의 크기와 관련있으므로 반드시 이 위치에서 구해야 한다.
                  //}---------------------------------------------------------------------------------

                  _dbgView_Width  = this->Width - d_gutter_width - ide_editor_Form->_scroll_v_Form->Width;

                  _dbgView_Height = 2 + strAreaHeight + 2;

              //}

              //[바탕색]
              //{
                  //바탕을 [적색] 으로 만들어 [오류] 임을 강력하게 알려준다.
                  _dbgView_bmp->Canvas->Brush->Color = clRed;//_dbgView_BackColor;
                  _dbgView_bmp->Canvas->FillRect(_dbgView_bmp->Canvas->ClipRect);

              //}

              //[<tree> 모양 내기]
              //{
                  //[!]{------------------------
                  //<[x]> 기호만 그려주면 된다.
                  //}---------------------------

                  //<[x]> [엄지그림] 을 표시한다.
                  BMP_Copy_Transparent(_bmp_tree_x, 0, 0, _bmp_tree_x->Width, _bmp_tree_x->Height,
                                       _dbgView_bmp, 3, 4, 9, 9,
                                       -1);

              //}

              //[내용 출력]
              //{
                  FONT_Out_StyleString2(_dbgView_bmp, &_dbgView_font, 0, 2,
                                        _dbgView_FontColor, _dbgView_BackColor, true, d_FONTSTYLE_default,
                                        _dbgViewDspInfo.displayStr,
                                        d_FONT_underline_no, true, 0, _dbgView_FontColor,
                                        &strAreaWidth, &strAreaHeight);

              //}

              //[닫기 버튼]
              //{
                  //[2011.06.26.일][추가!!!]{-----------
                  //[닫기] 버튼을 맨 오른쪽에 그려준다.
                  //}-----------------------------------

                  //[영역정보]
                  //{
                      //[2011.06.29.수][추가!!!]
                      _dbgView_bmp_Close_TRect.Left   = _dbgView_Width - _dbgView_bmp_Close->Width - 3;
                      _dbgView_bmp_Close_TRect.Top    = 3;
                      _dbgView_bmp_Close_TRect.Right  = _dbgView_bmp_Close_TRect.Left + 11;
                      _dbgView_bmp_Close_TRect.Bottom = _dbgView_bmp_Close_TRect.Top + 11;

                  //}

                  BMP_Copy_Transparent(_dbgView_bmp_Close, 0, 0, _dbgView_bmp_Close->Width, _dbgView_bmp_Close->Height,
                                       _dbgView_bmp,
                                       _dbgView_bmp_Close_TRect.Left, _dbgView_bmp_Close_TRect.Top,
                                       _dbgView_bmp_Close_TRect.Width(), _dbgView_bmp_Close_TRect.Height(),
                                       -1);

              //}

              //[검증식으로 이동]
              //{
                  //[2011.06.27.월][추가!!!]{-----------------------------
                  //[검증식으로 이동] 버튼을 [닫기] 버튼 안쪽에 올려준다.
                  //}-----------------------------------------------------

                  //[영역정보]
                  //{
                      //[2011.06.29.수][추가!!!]
                      _dbgView_bmp_GoBlock_TRect.Left   = _dbgView_Width - _dbgView_bmp_Close->Width - 3 - _dbgView_bmp_GoBlock->Width - 3;
                      _dbgView_bmp_GoBlock_TRect.Top    = 3;
                      _dbgView_bmp_GoBlock_TRect.Right  = _dbgView_bmp_GoBlock_TRect.Left + 11;
                      _dbgView_bmp_GoBlock_TRect.Bottom = _dbgView_bmp_GoBlock_TRect.Top + 11;

                  //}

                  BMP_Copy_Transparent(_dbgView_bmp_GoBlock, 0, 0, _dbgView_bmp_GoBlock->Width, _dbgView_bmp_GoBlock->Height,
                                       _dbgView_bmp,
                                       _dbgView_bmp_GoBlock_TRect.Left, _dbgView_bmp_GoBlock_TRect.Top,
                                       _dbgView_bmp_GoBlock_TRect.Width(), _dbgView_bmp_GoBlock_TRect.Height(),
                                       clWhite);

              //}

              //[테두리]
              //{
                  _dbgView_bmp->Canvas->Pen->Color   = _dbgView_BorderColor;
                  _dbgView_bmp->Canvas->Pen->Width   = 1;
                  _dbgView_bmp->Canvas->Brush->Style = bsClear;
                  _dbgView_bmp->Canvas->Rectangle(0, 0, _dbgView_Width, _dbgView_Height);

              //}

            } break;

          }

          //고정보기 처리가 끝났으므로 다음으로 넘긴다.
          goto lbDraw;

      //}

  //}

  lbDraw:

  //[복사]
  //{
      //[!]{--------------------------------
      //실제 편집기의 해당 위치에 복사한다.
      //}-----------------------------------

      _DbgView_Draw();

  //}

  //[보이기 설정]
  //{
      //[2011.06.23.목][추가!!!]{-------------------------
      //[검증식 보기판] 이 보이는 상태라는 것을 알려준다.
      //}-------------------------------------------------

      _dbgView_Visible = true;

  //}

}

void __fastcall Teditor_edit_Form::_DbgView_Draw(void)
{
  //[2011.06.20.월][생성!!!]{---------------------------------------------------
  //현재 [선택영역] 의 첫행 바로 아래에 복사해 준다.
  //
  //[2011.06.23.목][추가!!!]----------------------------------------------------
  //표시 할때 자동으로 계산되는 표시위치를 (x, y) 로 관리해야 한다.
  //이는 [줄이동] 시에도 계속 보여지기 때문이며, [MouseDown] 등 이벤트 부분에서
  //이 [검증식 표시판] 영역을 먼저 처리해 주기 위한 것이다.
  //
  //[주의!!!]-------------------------------------------------------------------
  //[검증판] 안으로 들어가는 경우는 [검증판] 보다 먼저 그리고 [검증판] 을 다시
  //위에 복사해주는 방법을 사용하지 않고, 아예 [검증판] 영역과 겹치는 부분을
  //제외하고 복사하는 방법을 사용한다.
  //이게 더 간단하고 시간을 절약할수 있다.
  //}---------------------------------------------------------------------------

  //[VAR]
  //{
      //[2011.06.23.목][추가!!!]
      int    leftOfs;

      //[2011.06.24.금][추가!!!]
      struct CARETINFO  select_start;
      struct CARETINFO  select_end;

  //}

  //[처리 할 상태인가?]
  //{
      //[2011.06.23.목][추가!!!]{---------
      //유효하고, 보이는 경우만 처리한다.
      //}---------------------------------

      if(!((_dbgView_Enable == true) && (_dbgView_Visible == true) &&
           //[2011.06.30.목][추가!!!
           //반드시 <*.c> 문서의 경우만 처리해야 한다.
           (_fileKind == d_Editor_FileKind_c))) return;

  //}

  //[<기본보기/고정보기> 구분 처리]
  //{
      //[2011.06.26.일][추가!!!]{-------------
      //[기본보기/고정보기] 를 구분 처리한다.
      //}-------------------------------------

      if(_dbgView_FixView == false)
      {
        //[선택 영역 정보 얻기]
        //{
            //[2011.06.24.금][추가!!!]{-----------------------
            //[선택영역] 의 [시작/끝] 위치를 정리하여 얻는다.
            //단, [선택영역] 이 없는 경우는 바로 종료한다.
            //}-----------------------------------------------

            if(_SELECT_Get_StartEndIndex(&select_start, &select_end) != true) return;

        //}

        //[표시 좌표 계산]
        //{
            //[2011.06.23.목][추가!!!]{------------------------------------------------
            //보인 상태에서 줄이동시 같이 이동하므로 반드시 여기서 [좌표] 를 계산한다.
            //}------------------------------------------------------------------------

            _dbgView_X = _text_org_x + select_start.caret_x;

            _dbgView_Y = _text_org_y + select_start.caret_y + _line_height;

        //}

        //[고속 복사]
        //{
            //[2011.06.23.목][수정!!!]{----------------------------------
            //[검증판] 과 겹치는 경우는 겹치는 영역을 제외하고 복사한다.
            //}----------------------------------------------------------

            if(_dbgView_X <= d_gutter_width)
            {
              //[!]{--------------------------------------
              //[검증판] 과 영역이 겹치는 것이 있는 경우.
              //}-----------------------------------------

              //[검증판] 과 겹치는 영역의 크기 계산.
              leftOfs = d_gutter_width - _dbgView_X;

              //[검증판] 과 겹치는 영역을 제외하고 복사한다.
              BMP_Copy_Transparent(//출발지 정보.
                                   _dbgView_bmp, leftOfs, 0, _dbgView_Width - leftOfs, _dbgView_Height,
                                   //도착지 정보.
                                   _bmp_, _dbgView_X + leftOfs, _dbgView_Y,
                                   _bmp_->Width, _bmp_->Height,
                                   //투명 지정 색.
                                   _dbgView_TransColor);

            }
            else
            {
              BMP_Copy_Transparent(//출발지 정보.
                                   _dbgView_bmp, 0, 0, _dbgView_Width, _dbgView_Height,
                                   //도착지 정보.
                                   _bmp_, _dbgView_X, _dbgView_Y,
                                   _bmp_->Width, _bmp_->Height,
                                   //투명 지정 색.
                                   _dbgView_TransColor);

            }

        //}

        //[검증식 추가 버튼]
        //{
            //[2011.07.10.일][추가!!!]{------------------------------------------------------------
            //[검증식 추가 버튼] 은 [검증식 보기판] 이 보이는 경우만 처리하고,
            //[검증식 보기판] 의 [좌표] 가 확정되어야 [좌표] 가 확정될수 있으므로 여기서 처리한다.
            //단, 이것도 [검증판] 과 겹치는 경우를 구분하여 처리해야 한다.
            //
            //[주의!!!]----------------------------------------------------------------------------
            //반드시 [검증식 보기판] 이 [+] 인 상태에서만 보여야 한다.
            //}------------------------------------------------------------------------------------

            //[<+> 상태인가?]
            //{
                //[+] 상태가 아니라면 보여주지 않아야 한다.
                if(_dbgView_State != '+') return;

            //}

            //[좌표계산]
            //{
                // Y 는 같고, X 는 항상 [검증식 보기판] 의 오른쪽 <4pixel> 위치에 존재해야 한다.
                _dbgView_bmp_AddBtn_TRect.Left   = _dbgView_X + _dbgView_Width + 4;
                _dbgView_bmp_AddBtn_TRect.Top    = _dbgView_Y;

                //크기는 고정 크기다.
                _dbgView_bmp_AddBtn_TRect.Right  = _dbgView_bmp_AddBtn_TRect.Left + 17;
                _dbgView_bmp_AddBtn_TRect.Bottom = _dbgView_bmp_AddBtn_TRect.Top  + 17;

            //}

            //[편집기에 표시]
            //{
                //[!]{-------------------------------------------------------
                //[검증판] 과 겹치는 경우는 겹치는 영역을 제외하고 복사한다.
                //}----------------------------------------------------------

                if(_dbgView_bmp_AddBtn_TRect.Left <= d_gutter_width)
                {
                  //[!]{--------------------------------------
                  //[검증판] 과 영역이 겹치는 것이 있는 경우.
                  //}-----------------------------------------

                  //[검증판] 과 겹치는 영역의 크기 계산.
                  leftOfs = d_gutter_width - _dbgView_bmp_AddBtn_TRect.Left;

                  //[검증판] 과 겹치는 영역을 제외하고 복사한다.
                  BMP_Copy_Transparent(//출발지 정보.
                                       _dbgView_bmp_AddBtn, leftOfs, 0, _dbgView_bmp_AddBtn_TRect.Width() - leftOfs, _dbgView_bmp_AddBtn_TRect.Height(),
                                       //도착지 정보.
                                       _bmp_, _dbgView_bmp_AddBtn_TRect.Left + leftOfs, _dbgView_bmp_AddBtn_TRect.Top,
                                       _bmp_->Width, _bmp_->Height,
                                       //투명 지정 색.
                                       _dbgView_TransColor);

                }
                else
                {
                  BMP_Copy_Transparent(//출발지 정보.
                                       _dbgView_bmp_AddBtn, 0, 0, _dbgView_bmp_AddBtn_TRect.Width(), _dbgView_bmp_AddBtn_TRect.Height(),
                                       //도착지 정보.
                                       _bmp_, _dbgView_bmp_AddBtn_TRect.Left, _dbgView_bmp_AddBtn_TRect.Top,
                                       _bmp_->Width, _bmp_->Height,
                                       //투명 지정 색.
                                       _dbgView_TransColor);

                }

            //}

        //}

      }
      else
      {
        //[2011.06.26.일][추가!!!]{---
        //[고정보기] 의 경우.
        //}---------------------------

        //[표시 좌표 계산]
        //{
            //[!]{-----------------------------------------------------------------------
            //[고정보기] 상태인 경우는 [편집기] 의 보이는 영역의 모서리에 표시해야 한다.
            //}--------------------------------------------------------------------------

            _dbgView_X = d_gutter_width - 1;

            _dbgView_Y = 0;

        //}

        //[고속 복사]
        //{
            //[2011.06.23.목][수정!!!]{----------------------------------
            //[검증판] 과 겹치는 경우는 겹치는 영역을 제외하고 복사한다.
            //
            //[2011.06.27.월][수정!!!]-----------------------------------
            //[투명] 기능이 없으므로 <BitBlt()> 로 고속 처리한다.
            //}----------------------------------------------------------

            BitBlt(_bmp_->Canvas->Handle, _dbgView_X, _dbgView_Y, _dbgView_Width, _dbgView_Height,
                   _dbgView_bmp->Canvas->Handle, 0, 0, SRCCOPY);

            /*
            BMP_Copy_Transparent(//출발지 정보.
                                 _dbgView_bmp, 0, 0, _dbgView_Width, _dbgView_Height,
                                 //도착지 정보.
                                 _bmp_, _dbgView_X, _dbgView_Y,
                                 _bmp_->Width, _bmp_->Height,
                                 //투명 지정 색.
                                 _dbgView_TransColor);
            */

        //}

      }

  //}

}

void __fastcall Teditor_edit_Form::_DbgView_AddBtn_Shape(void)
{
  //[2011.07.10.일][생성!!!]{-----------------------------------------
  //[편집기] 상에 직접 표시할 [검증식 추가 버튼] 을 그려준다.
  //
  //[검증식 보기판] 이 그려질때 이 함수가 호출되어 자동으로 그려진다.
  //}-----------------------------------------------------------------

  //[바탕색]
  //{
      //바탕을 일단 배경색으로 지운다.
      _dbgView_bmp_AddBtn->Canvas->Brush->Color = _dbgView_BackColor;
      _dbgView_bmp_AddBtn->Canvas->FillRect(_dbgView_bmp_AddBtn->Canvas->ClipRect);

  //}

  //[내부 그림 올리기]
  //{
      //[!]{-------------------------------------------------
      //<_dbgView_bmp_AddBtn> 영역의 (2, 2) 위치에 올려준다.
      //}----------------------------------------------------

      BMP_Copy_Transparent(_dbgView_bmp_AddBtn_icon, 0, 0, _dbgView_bmp_AddBtn_icon->Width, _dbgView_bmp_AddBtn_icon->Height,
                           _dbgView_bmp_AddBtn, 2, 2, 13, 13,
                           -1);

  //}

  //[테두리]
  //{
      _dbgView_bmp_AddBtn->Canvas->Pen->Color   = _dbgView_BorderColor;
      _dbgView_bmp_AddBtn->Canvas->Pen->Width   = 1;
      _dbgView_bmp_AddBtn->Canvas->Brush->Style = bsClear;
      _dbgView_bmp_AddBtn->Canvas->Rectangle(0, 0, _dbgView_bmp_AddBtn->Width, _dbgView_bmp_AddBtn->Height);

  //}

  //[반영]
  //{
      //[!]{-----------------------------------------------------------------------------------
      //실제 [편집기] 에 반영은 <_DbgView_Draw()> 에서 처리된다.
      //이는 [검증식 보기판] 의 위치가 실제 <_DbgView_Draw()> 에서 그려질때 확정되기 때문이다.
      //}--------------------------------------------------------------------------------------

      //여기서는 처리하지 않는다.

  //}

}

void __fastcall Teditor_edit_Form::_DbgView_Exe(void)
{
  //[2011.06.22.수][생성!!!]{--------------------------------------------
  //현재 선택된 [검증식] 을 계산하고 결과를 [검증식 보기판] 에 보여준다.
  //
  //[2018.07.24.화][수정!!!]---------------------------------------------
  //}--------------------------------------------------------------------

  //[처리 할 상태인가?]
  //{
      //[2011.06.30.목][추가!!!]{-----------------------
      //유효하고, 보이고, <*.c> 문서인 경우만 처리한다.
      //}-----------------------------------------------

      if(!((_dbgView_Enable == true) && (_dbgView_Visible == true) &&
           //[2011.06.30.목][추가!!!
           //반드시 <*.c> 문서의 경우만 처리해야 한다.
           (_fileKind == d_Editor_FileKind_c))) return;

  //}


  //[버튼 동작 대기열 등록]
  //{
      //[2011.07.01.금][중요추가!!!]{------------------------------
      //현재 <ACK> 를 확인하고 있는 중일수 있으므로 이경우는 바로
      //동작되지 않고 일단 [동작 대기열] 에 등록해 놓은뒤에
      //<ACK> 확인용 [타이머] 가 종료되면 자동으로 동작되게 한다.
      //
      //[참고!!!]--------------------------------------------------
      //원래 [검증버튼] 을 위한 것이었으나 실제 [맷돌] 을 대상으로
      //처리하는 과정은 동일하므로 같은 방법을 적용한다.
      //}----------------------------------------------------------

      if(main_Form->timeOut_Timer->Enabled == true)
      {
        main_Form->BtnQueue_Event = _DbgView_Exe;
        main_Form->btnQueue_Timer->Enabled = true;
        return;

      }

  //}

  //[2018.07.24.화][추가!!!]{----------------------------------------------
  //실제 이 함수의 처리 [시작/끝] 을 알려준다.
  //[검증식:문자열 전체 보기] 와 관련이 있으며 같은 날짜 주석 내용을 참고.
  //실제 <DebugViewDisplay_Make_DisplayStr()> 함수에서 판별에 사용된다.
  //}----------------------------------------------------------------------

  if(_isDblClicked == true) { _isDblClick = true; }
  //{
      //[초기화]
      //{
          DebugViewInfo_Init(&_dbgViewInfo);

      //}

      if(DebugView_EditorSelExpStr(&_dbgViewInfo, &_dbgViewDspInfo) == true)
      {
        //[표시종류 : 내용보기] 로 지정한다.
        _dbgView_State = '-';

        //자동으로 [보기종류] 에 따라 모양을 만들어준다.
        _DbgView_Shape();

        //[<기본/고정 보기> 구분 처리]
        //{
            //[2011.06.27.월][수정!!!]
            if(_dbgView_FixView == false)
            {
              //[기본보기] 의 경우.
              //실제는 최대 5행 범위이지만 넉넉하게 6행으로 설정한다.
              //[보기행] 의 바로 아래에 위치해야한다------v
              _EditBuf_LineTextX(_SELECT_StartLineNum() + 1, 7, true, true);

            }
            else
            {
              //[고정보기] 의 경우.
              //무조건 [편집기] 가장 위에 보여지므로 보이는 가장 윗행에 출력한다.
              _EditBuf_LineTextX(_linetop_linenumber, 7, true, true);

            }

        //}

      }
      else
      {
        //[2011.06.24.금][추가!!!]{---
        //[검증식] 이 오류인 경우다.
        //}---------------------------

        //[선택된 검증식이 없는 경우인가?]
        //{
            //[2011.06.30.목][추가!!!]{-----------------------------------------------
            //아예 선택 문자열이 없는 경우도 이곳으로 오게 되는데,
            //이 경우는 [검증식 오류] 가 아니므로 아무것도 처리하지 않는 것으로 한다.
            //보이지 않게 만든다.
            //}-----------------------------------------------------------------------

            if(_dbgViewInfo.expBuf[0] == '\0')
            {
              _dbgView_Visible = false;

              //[2018.07.24.화][추가!!!]{---
              _isDblClick   = false;
              _isDblClicked = false;
              //}---------------------------

              return;

            }

        //}

        //[표시종류 : 내용보기] 로 지정한다.
        _dbgView_State = 'x';

        //자동으로 [보기종류] 에 따라 모양을 만들어준다.
        _DbgView_Shape();

        //[<기본/고정 보기> 구분 처리]
        //{
            //[2011.06.27.월][수정!!!]

            //[주의!!!]{---------------------------------------------------------------
            //실제는 1행 범위이지만 이전에 최대 5행이 표시된 경우 나머지 행이 그려지지
            //않으므로이전의 행도 다시 그려질수 있도록 넉넉하게 6행으로 설정한다.
            //}------------------------------------------------------------------------

            if(_dbgView_FixView == false)
            {
              //[기본보기] 의 경우.
              //실제는 최대 5행 범위이지만 넉넉하게 6행으로 설정한다.
              //[보기행] 의 바로 아래에 위치해야한다------v
              _EditBuf_LineTextX(_SELECT_StartLineNum() + 1, 7, true, true);

            }
            else
            {
              //[고정보기] 의 경우.
              //무조건 [편집기] 가장 위에 보여지므로 보이는 가장 윗행에 출력한다.
              _EditBuf_LineTextX(_linetop_linenumber, 7, true, true);

            }

        //}

      }

  //}
  //<false> 는 무조건 초기화 의미로 설정한다.
  _isDblClick   = false;
  _isDblClicked = false;

}

void __fastcall Teditor_edit_Form::_DbgView_DebugExe(void)
{
  //[2011.06.22.수][생성!!!]{--------------------------------------------------
  //<debug.cpp:Debug_Mark_Line()> 함수안에서 <Debug_Tree_Reg()> 와 같이
  //지정행이 이동하는 경우 계속 정보를 갱신한다.
  //단, <[-]> 인 경우만 처리해야 한다.
  //
  //[주의!!!]------------------------------------------------------------------
  //만일, 현재 함수가 아닌 다른 함수로 넘어간 경우는 [검증식] 에 [지역변수] 가
  //사용되어 계산 오류가 난다.
  //이경우는 자동으로 <[x]> 로 처리되므로 신경쓰지 않는다.
  //}--------------------------------------------------------------------------

  //[처리 할 상태인가?]
  //{
      //[2011.06.30.목][추가!!!]{-----------------------
      //유효하고, 보이고, <*.c> 문서인 경우만 처리한다.
      //}-----------------------------------------------

      if(!((_dbgView_Enable == true) && (_dbgView_Visible == true) &&
           //[2011.06.30.목][추가!!!
           //반드시 <*.c> 문서의 경우만 처리해야 한다.
           (_fileKind == d_Editor_FileKind_c))) return;

  //}


  //[버튼 동작 대기열 등록]
  //{
      //[2011.07.01.금][중요추가!!!]{------------------------------
      //현재 <ACK> 를 확인하고 있는 중일수 있으므로 이경우는 바로
      //동작되지 않고 일단 [동작 대기열] 에 등록해 놓은뒤에
      //<ACK> 확인용 [타이머] 가 종료되면 자동으로 동작되게 한다.
      //
      //[참고!!!]--------------------------------------------------
      //원래 [검증버튼] 을 위한 것이었으나 실제 [맷돌] 을 대상으로
      //처리하는 과정은 동일하므로 같은 방법을 적용한다.
      //}----------------------------------------------------------

      if(main_Form->timeOut_Timer->Enabled == true)
      {
        main_Form->BtnQueue_Event = _DbgView_DebugExe;
        main_Form->btnQueue_Timer->Enabled = true;
        return;

      }

  //}


  //[검증식 계산 결과 보기 상태인가?]
  //{
      //[!]{-------------------------------------------------------------------------------
      //이미 펼져져 있는 경우만 갱신해야 한다.
      //
      //[2011.07.04.월][중요수정!!!]-------------------------------------------------------
      //[검증식] 에 [지역변수] 가 있을 경우, 함수를 호출하게 되면 [함수영역] 이 변경되어
      //현재의 [검증식] 은 계산할수 없게 되어 <x> 로 처리된다.
      //그러나, 다시 검증이 계속되어 해당 [함수영역] 으로 되돌아 오는 경우는 자동으로
      //계산되어 값이 다시 보여져야 한다.
      //이를 위하여 현재 <x> 인 경우라도 계산을 하여 이상이 없으면 [검증] 시에는 보여준다.
      //}----------------------------------------------------------------------------------

      if((_dbgView_State != '-') && (_dbgView_State != 'x')) return;

  //}

  //[초기화]
  //{
      DebugViewInfo_Init(&_dbgViewInfo);

  //}

  if(DebugView_EditorSelExpStr(&_dbgViewInfo, &_dbgViewDspInfo) == true)
  {
    //[표시종류 : 내용보기] 로 지정한다.
    _dbgView_State = '-';

    //자동으로 [보기종류] 에 따라 모양을 만들어준다.
    _DbgView_Shape();

    //[<기본/고정 보기> 구분 처리]
    //{
        //[2011.06.27.월][수정!!!]
        if(_dbgView_FixView == false)
        {
          //[기본보기] 의 경우.
          //실제는 최대 5행 범위이지만 넉넉하게 6행으로 설정한다.
          //[보기행] 의 바로 아래에 위치해야한다------v
          _EditBuf_LineTextX(_SELECT_StartLineNum() + 1, 7, true, true);

        }
        else
        {
          //[고정보기] 의 경우.
          //무조건 [편집기] 가장 위에 보여지므로 보이는 가장 윗행에 출력한다.
          _EditBuf_LineTextX(_linetop_linenumber, 7, true, true);

        }

    //}

  }
  else
  {
    //[2011.06.24.금][추가!!!]{---
    //[검증식] 이 오류인 경우다.
    //}---------------------------

    //[선택된 검증식이 없는 경우인가?]
    //{
        //[2011.06.30.목][추가!!!]{-----------------------------------------------
        //아예 선택 문자열이 없는 경우도 이곳으로 오게 되는데,
        //이 경우는 [검증식 오류] 가 아니므로 아무것도 처리하지 않는 것으로 한다.
        //보이지 않게 만든다.
        //}-----------------------------------------------------------------------

        if(_dbgViewInfo.expBuf[0] == '\0')
        {
          _dbgView_Visible = false;

          return;

        }

    //}

    //[표시종류 : 내용보기] 로 지정한다.
    _dbgView_State = 'x';

    //자동으로 [보기종류] 에 따라 모양을 만들어준다.
    _DbgView_Shape();

    //[<기본/고정 보기> 구분 처리]
    //{
        //[2011.06.27.월][수정!!!]

        //[주의!!!]{---------------------------------------------------------------
        //실제는 1행 범위이지만 이전에 최대 5행이 표시된 경우 나머지 행이 그려지지
        //않으므로이전의 행도 다시 그려질수 있도록 넉넉하게 6행으로 설정한다.
        //}------------------------------------------------------------------------

        if(_dbgView_FixView == false)
        {
          //[기본보기] 의 경우.
          //실제는 최대 5행 범위이지만 넉넉하게 6행으로 설정한다.
          //[보기행] 의 바로 아래에 위치해야한다------v
          _EditBuf_LineTextX(_SELECT_StartLineNum() + 1, 7, true, true);

        }
        else
        {
          //[고정보기] 의 경우.
          //무조건 [편집기] 가장 위에 보여지므로 보이는 가장 윗행에 출력한다.
          _EditBuf_LineTextX(_linetop_linenumber, 7, true, true);

        }

    //}

  }

}

void __fastcall Teditor_edit_Form::_DbgView_ModeChange(void)
{
  //[2011.06.23.목][생성!!!]{-------------------------------------------------
  //함수가 실행될때마다 [2진수/10진수/16진수] 로 계속 표시형식을 바꾼다.
  //[표기형식] 을 변경후 다시 [선택영역 검증식] 을 계산하면 자동 처리된다.
  //
  //[2018.07.24.화][수정!!!]--------------------------------------------------
  //}-------------------------------------------------------------------------

  //[처리 할 상태인가?]
  //{
      //[2011.06.30.목][추가!!!]{-----------------------
      //유효하고, 보이고, <*.c> 문서인 경우만 처리한다.
      //}-----------------------------------------------

      if(!((_dbgView_Enable == true) && (_dbgView_Visible == true) &&
           //[2011.06.30.목][추가!!!
           //반드시 <*.c> 문서의 경우만 처리해야 한다.
           (_fileKind == d_Editor_FileKind_c))) return;

  //}

  //[표기형식 교체]
  //{    
      //[!]{-------------------------------------------------------------------------
      //[2진수] => [10진수] => [16진수] 형식으로 돌려 준다.
      //
      //[2011.07.01.금][수정!!!]-----------------------------------------------------
      //이전의 <_ide_option:환경변수> 를 사용하지 않고 <_dbgViewDspInfo.viewKind> 를
      //직접 사용하는 것으로 수정한다.
      //이는 [문서마다] 개별적으로 [2/10/16 진수] 보기를 적용하기 위한 것이다.
      //}----------------------------------------------------------------------------

      switch(_dbgViewDspInfo.viewKind)
      {
        case 10 : { _dbgViewDspInfo.viewKind = 16; } break;

        case 16 : { _dbgViewDspInfo.viewKind = 2;  } break;

        //[2018.07.24.화][수정!!!]
        //[2진수] => [문자열] 로 변경.
        case 2  : { _dbgViewDspInfo.viewKind = '$'; } break;

        //[2018.07.24.화][추가!!!]
        //[문자열] => [10진수] 로 변경.
        case '$' : { _dbgViewDspInfo.viewKind = 10;  } break;

        //이럴 경우는 없겠으나 혹시라도 아무것도 해당하지 않는다면 [16진수] 로 표기한다.
        default : { _dbgViewDspInfo.viewKind = 16; } break;

      }

  //}

  //[다시 계산 표기]
  //{
      _DbgView_Exe();

  //}

}

void __fastcall Teditor_edit_Form::_DbgView_MakeDspExpStr(//지정폭.
                                                          int    pSetWidth,
                                                          //표시할 검증식 문자열.
                                                          char  *rStr)
{
  //[2011.06.28.화][생성!!!]{------------------------------------------------------------
  //[선택된 검증식] 문자열을 지정된 형식으로 바꿔주되,
  //지정된 폭에 맞게 길이를 조정해 준다.
  //[검증식] 은 이미 []
  //
  //예) "[ 검증식 문자열------... ]"
  //
  //문자열이 지정된 표시 영역 폭을 넘는 경우는 "..." 을 붙여주어야 한다.
  //
  //[검증식이 여러개 행으로 구성된 경우]-------------------------------------------------
  //
  //[첫 행] 만표시하고 길이가 폭을 만족 시키는 경우라도 뒤에 "..." 를 붙여준다.
  //
  // "[ 첫행문자열... ]"
  //
  //[주의!!!]----------------------------------------------------------------------------
  //[검증식] 은 [첫 행] 만을 대상으로 하므로 검사 대상 문자열을 추출할때 [첫 행]
  //만 추출해야 한다.
  //또한, 무한 정 긴 문자열을 검사할 필요가 없으므로 1K 정도의 문자열만을 대상으로 한다.
  //이는 <_dbgViewInfo.expBuf[]> 에 이미 정리가 돼 있다.
  //
  //[2011.07.17.일][수정!!!]-------------------------------------------------------------
  //<debug_view:DebugView_Get_ExpStr_fromEditor()> 에서 검증식 문자열출 추출할때
  //[주석제거/한행으로 앞/뒤 여백없이 정리] 된 문자열을 저장하는 것으로 수정되었으므로
  //여기서는 이전과 달리 <Str_Width_Ellipsis()> 를 사용하여 "..." 를 붙이는 처리만 한다.
  //즉, 여기서 처리되는 [검증식 문자열] 은 [한개 행] 으로 된 문자열만 처리하면 된다.
  //
  //단, "[ 검증식... ]" 의 형식이 되도록 "[ ]" 를 추가해 주어야 한다.
  //
  //[결과!!!]----------------------------------------------------------------------------
  //아주 간단하고 확실하게 처리되는 것을 확인하였다.]
  //}------------------------------------------------------------------------------------

  //[VAR]
  //{
      int  svx;

  //}

  //[안전장치]
  //{
      //[처리할 문자열], [반환할 문자열] 이 존재하지 않는 경우는 처리하지 않는다.
      if(rStr == NULL) return;

  //}

  //[검증식 문자열 처리]
  //{
      //[2011.07.17.일][추가!!!]{--------------------------------------------------------------
      //[검증식 문자열] 이 표시 영역에 다 표시할수 없을때는 길이를 조정하고 "..." 를 붙여준다.
      //}--------------------------------------------------------------------------------------

      //먼저 "[ " 를 붙여주면서 동시게 처리된 크기를 얻는다.
      //이 위치부터 다음 문자열을 저장하게 된다.
      svx = STR_Assign(rStr, "[ ");

      //[검증식 문자열] 처리.
      Str_Width_Ellipsis(//검증식 문자열 원본.
                         _dbgViewInfo.expBuf,
                         //적용할 글꼴.
                         &(editor_edit_Form->_dbgView_font),
                         //기본형식을 적용한다.
                         d_FONTSTYLE_default,
                         //지정 출력 폭에서 "[  ]" 4개 문자의 출력폭을 제외시킨다.
                         //이 사이에 [검증식 문자열...] 이 출력되기 때문이다.
                         pSetWidth - (_dbgView_EngWidth*4),
                         //처리된 문자열("[ " 다음부터 저장한다).
                         &(rStr[svx]));

      //" ]" 를 붙여준다.
      STR_Add(rStr, " ]");

  //}

}

void __fastcall Teditor_edit_Form::_Event_dbgView_bmp_Close(void)
{
  //[2011.06.29.수][생성!!!]{---------
  //[기본/고정 보기] 전환을 처리한다.
  //}---------------------------------

  //[이전것 지우기]
  //{
      //[주의!!!]{-----------------------------------------------------
      //반드시 이전 그려진 것을 지우고 다시 새 위치에 보여주어야 한다.
      //}--------------------------------------------------------------

      if(_dbgView_FixView == false)
      {
        //[기본보기] 의 경우.
        //실제는 최대 5행 범위이지만 넉넉하게 6행으로 설정한다.
        //[보기행] 의 바로 아래에 위치해야한다------v
        _EditBuf_LineTextX(_SELECT_StartLineNum() + 1, 7, false, true);

      }
      else
      {
        //[고정보기] 의 경우.
        //무조건 [편집기] 가장 위에 보여지므로 보이는 가장 윗행에 출력한다.
        _EditBuf_LineTextX(_linetop_linenumber, 7, false, true);

      }

  //}

  //[설정 변환
  //{
      //[기본<=>고정] 으로 변환한다.
      _dbgView_FixView = !_dbgView_FixView;

      //다시 모양을 만든다.
      _DbgView_Shape();

  //}

  //[새 위치에 출력하기]
  //{
      //[주의!!!]{-----------------------------------------------------
      //반드시 이전 그려진 것을 지우고 다시 새 위치에 보여주어야 한다.
      //}--------------------------------------------------------------

      if(_dbgView_FixView == false)
      {
        //[선택영역 보이기]{--------------------------------------------------------
        _Caret_ViewAlways_Middle(false, //위쪽은 기본 보이는 영역으로.
                                 true); //아래쪽의 경우는 무조건 중간에 위치시키기.
        //}-------------------------------------------------------------------------

        //[기본보기] 의 경우.
        //실제는 최대 5행 범위이지만 넉넉하게 6행으로 설정한다.
        //[보기행] 의 바로 아래에 위치해야한다------v
        _EditBuf_LineTextX(_SELECT_StartLineNum() + 1, 7, true, true);

      }
      else
      {
        //[고정보기] 의 경우.
        //무조건 [편집기] 가장 위에 보여지므로 보이는 가장 윗행에 출력한다.
        _EditBuf_LineTextX(_linetop_linenumber, 7, true, true);

      }

  //}

}

void __fastcall Teditor_edit_Form::_Event_dbgView_bmp_GoBlock(void)
{
  //[2011.06.29.수][생성!!!]{---------------
  //[선택 검증식으로 이동] 기능을 처리한다.
  //}---------------------------------------

  //[선택영역 보이기]{--------------------------------------------------
  _Caret_ViewAlways_Middle(true,  //위쪽으로 사라진 경우 중간에 위치.
                           true); //아래쪽으로 사라진 경우 중간에 위치.
  //}-------------------------------------------------------------------

}

void __fastcall Teditor_edit_Form::_DbgView_bmp_Close_Down(bool  pTdownFup)
{
  //[2011.06.29.수][생성!!!]

  if(pTdownFup == true)
  {
    _dbgView_bmp_Close_Down = true;

    //[다시 그리기]
    //{
        Bmp_Area_ChangeColor_2(_dbgView_bmp,
                               _dbgView_bmp_Close_TRect.Left,
                               _dbgView_bmp_Close_TRect.Top,
                               _dbgView_bmp_Close_TRect.Width(),
                               _dbgView_bmp_Close_TRect.Height(),
                               clBlack, clWhite,
                               clWhite, clBlack);

    //}

  }
  else
  {
    _dbgView_bmp_Close_Down = false;

    //[다시 그리기]
    //{
        //이 경우는 다시 원본을 복사한다.
        BMP_Copy_Transparent(_dbgView_bmp_Close, 0, 0, _dbgView_bmp_Close->Width, _dbgView_bmp_Close->Height,
                             _dbgView_bmp,
                             _dbgView_bmp_Close_TRect.Left, _dbgView_bmp_Close_TRect.Top,
                             _dbgView_bmp_Close_TRect.Width(), _dbgView_bmp_Close_TRect.Height(),
                             -1);

    //}

  }

  //[반영]
  //{
      //[!]{---------------------------------------------------------------------
      //<기본/고정 보기> 를 구분하여 처리한다.
      //
      //[주의!!!]{---------------------------------------------------------------
      //실제는 1행 범위이지만 이전에 최대 5행이 표시된 경우 나머지 행이 그려지지
      //않으므로이전의 행도 다시 그려질수 있도록 넉넉하게 6행으로 설정한다.
      //}------------------------------------------------------------------------

      if(_dbgView_FixView == false)
      {
        //[기본보기] 의 경우.
        //실제는 최대 5행 범위이지만 넉넉하게 6행으로 설정한다.
        //[보기행] 의 바로 아래에 위치해야한다------v
        _EditBuf_LineTextX(_SELECT_StartLineNum() + 1, 7, true, true);

      }
      else
      {
        //[고정보기] 의 경우.
        //무조건 [편집기] 가장 위에 보여지므로 보이는 가장 윗행에 출력한다.
        _EditBuf_LineTextX(_linetop_linenumber, 7, true, true);

      }

  //}

}

void __fastcall Teditor_edit_Form::_DbgView_bmp_GoBlock_Down(bool  pTdownFup)
{
  //[2011.06.29.수][생성!!!]

  if(pTdownFup == true)
  {
    _dbgView_bmp_GoBlock_Down = true;

    //[다시 그리기]
    //{
        Bmp_Area_ChangeColor_2(_dbgView_bmp,
                               _dbgView_bmp_GoBlock_TRect.Left,
                               _dbgView_bmp_GoBlock_TRect.Top,
                               _dbgView_bmp_GoBlock_TRect.Width(),
                               _dbgView_bmp_GoBlock_TRect.Height(),
                               clBlack, clWhite,
                               clWhite, clBlack);

    //}

  }
  else
  {
    _dbgView_bmp_GoBlock_Down = false;

    //[다시 그리기]
    //{
        //이 경우는 다시 원본을 복사한다.
        BMP_Copy_Transparent(_dbgView_bmp_GoBlock, 0, 0, _dbgView_bmp_GoBlock->Width, _dbgView_bmp_GoBlock->Height,
                             _dbgView_bmp,
                             _dbgView_bmp_GoBlock_TRect.Left, _dbgView_bmp_GoBlock_TRect.Top,
                             _dbgView_bmp_GoBlock_TRect.Width(), _dbgView_bmp_GoBlock_TRect.Height(),
                             clWhite);

    //}

  }

  //[반영]
  //{
      //[!]{---------------------------------------------------------------------
      //<기본/고정 보기> 를 구분하여 처리한다.
      //
      //[주의!!!]{---------------------------------------------------------------
      //실제는 1행 범위이지만 이전에 최대 5행이 표시된 경우 나머지 행이 그려지지
      //않으므로이전의 행도 다시 그려질수 있도록 넉넉하게 6행으로 설정한다.
      //}------------------------------------------------------------------------

      if(_dbgView_FixView == false)
      {
        //[기본보기] 의 경우.
        //실제는 최대 5행 범위이지만 넉넉하게 6행으로 설정한다.
        //[보기행] 의 바로 아래에 위치해야한다------v
        _EditBuf_LineTextX(_SELECT_StartLineNum() + 1, 7, true, true);

      }
      else
      {
        //[고정보기] 의 경우.
        //무조건 [편집기] 가장 위에 보여지므로 보이는 가장 윗행에 출력한다.
        _EditBuf_LineTextX(_linetop_linenumber, 7, true, true);

      }

  //}

}

void __fastcall Teditor_edit_Form::_DbgView_bmp_AddBtn_Down(bool  pTdownFup)
{
  //[2011.07.10.일][생성!!!]{--------------------------
  //[검증식 추가 버튼] 의 내부 [그림] 만 반전시켜준다.
  //}--------------------------------------------------

  if(pTdownFup == true)
  {
    _dbgView_bmp_AddBtn_Down = true;

    //[다시 그리기]
    //{
        Bmp_Area_ChangeColor_2(_dbgView_bmp_AddBtn,
                               2,
                               2,
                               13,
                               13,
                               clBlack, clWhite,
                               clWhite, clBlack);

    //}

  }
  else
  {
    _dbgView_bmp_AddBtn_Down = false;

    //[다시 그리기]
    //{
        //이 경우는 다시 원본을 복사한다.
        BMP_Copy_Transparent(_dbgView_bmp_AddBtn_icon, 0, 0, _dbgView_bmp_AddBtn_icon->Width, _dbgView_bmp_AddBtn_icon->Height,
                             _dbgView_bmp_AddBtn, 2, 2, 13, 13,
                             -1);

    //}

  }

  //[반영]
  //{
      //[!]{---------------------------------------------------------------------
      //<기본/고정 보기> 를 구분하여 처리한다.
      //
      //[주의!!!]{---------------------------------------------------------------
      //실제는 1행 범위이지만 이전에 최대 5행이 표시된 경우 나머지 행이 그려지지
      //않으므로이전의 행도 다시 그려질수 있도록 넉넉하게 6행으로 설정한다.
      //}------------------------------------------------------------------------

      if(_dbgView_FixView == false)
      {
        //[기본보기] 의 경우.
        //실제는 최대 5행 범위이지만 넉넉하게 6행으로 설정한다.
        //[보기행] 의 바로 아래에 위치해야한다------v
        _EditBuf_LineTextX(_SELECT_StartLineNum() + 1, 7, true, true);

      }
      else
      {
        //[고정보기] 의 경우.
        //무조건 [편집기] 가장 위에 보여지므로 보이는 가장 윗행에 출력한다.
        _EditBuf_LineTextX(_linetop_linenumber, 7, true, true);

      }

  //}

}

void __fastcall Teditor_edit_Form::_Event_dbgView_bmp_AddBtn(void)
{
  //[2011.07.10.일][생성!!!]{--------------------------------------------
  //[선택된 검증식] 을 [검증식 보기창] 에 등록한다.
  //<filelistindex> 와 <funcrecindex> 를 모두 구해서 정리해 주어야 한다.
  //
  //처리가 복잡하므로 별도의 함수를 사용하여 처리한다.
  //}--------------------------------------------------------------------

  //[VAR]
  //{
      struct DBGEXP_TREE_INFO  info;

      //[2011.07.18.월][추가!!!]
      //추가된 [검증식] 의 항목위치.
      int  expItemIndex;

  //}

  //[버튼 동작 대기열 등록]
  //{
      //[2011.07.18.월][중요추가!!!]{------------------------------
      //현재 <ACK> 를 확인하고 있는 중일수 있으므로 이경우는 바로
      //동작되지 않고 일단 [동작 대기열] 에 등록해 놓은뒤에
      //<ACK> 확인용 [타이머] 가 종료되면 자동으로 동작되게 한다.
      //
      //[참고!!!]--------------------------------------------------
      //원래 [검증버튼] 을 위한 것이었으나 실제 [맷돌] 을 대상으로
      //처리하는 과정은 동일하므로 같은 방법을 적용한다.
      //}----------------------------------------------------------

      if(main_Form->timeOut_Timer->Enabled == true)
      {
        main_Form->BtnQueue_Event = _Event_dbgView_bmp_AddBtn;
        main_Form->btnQueue_Timer->Enabled = true;
        return;

      }

  //}

  //[초기화]
  //{
      DbgExpTreeInfo_Format(&info);

  //}

  //[검증식 추가정보 만들기]
  //{
      //오류가 발생한 경우는 바로 종료한다.
      if(DbgExpTreeInfo_Make_AddInfo(&info) != true) return;

  //}

  //[<검증식 정보창> 에 추가]
  //{
      //[2011.07.18.월][수정!!!]
      //추가된 [검증식 항목위치] 를 얻는다.
      //여기서는 이미 [검증식 정보창] 에 정보를 추가하였으므로 바로 종료하지 않고
      //[다시 그려주는 부분] 으로 이동해야 한다.
      if(Ide_Tree_DbgExp_Add(&info, &expItemIndex) != true) goto lbEnd;

  //}

  //[계산]
  //{
      //[!]{----------------------------
      //추가한 다음에 한번 계산해 준다.
      //}-------------------------------

      //추가한 [검증식 항목위치] 를 넘겨준다.
      //여기서는 이미 [검증식 정보창] 에 정보를 추가하였으므로 바로 종료하지 않고
      //[다시 그려주는 부분] 으로 이동해야 한다.
      if(DbgExpTree_View(expItemIndex) != true) goto lbEnd;

  //}

  lbEnd:

  //[표시]
  //{
      //tree 를 한번 그려준다.
      //if(tree_tree_Form->_tree_select_index == d_TREE_dbgExp)
      //{
          //[2011.07.22.금][추가!!!]{----------------------------------------------
          //반드시, [검증식 보기창] 이 보이는 경우만 처리한다.
          //이는 [동작대기열] 에 등록된 경우는 이미 다른 [Tree] 가 보이는 상태에서
          //[검증식 보기창] 이 그려질수 있기 때문이다.
          //}----------------------------------------------------------------------

          //tree_tree_Form->_TreeView(d_TREE_dbgExp, false);

      //}

      //강제로 [검증식 보기창] 으로 전환하면 자연스럽게 다시 그려져 반영된다.
      ide_tree_Form->_tabs_Form->_TabIndex(d_TREE_dbgExp);

  //}

}

void __fastcall Teditor_edit_Form::_DbgView_ExpStr_Edit(void)
{
  //[2012.09.19.수][생성!!!]{--------------------------------------
  //[검증식 문자열] 을 작성할 [한줄 편집기] 를 보여주는 것만 처리.
  //}--------------------------------------------------------------

  //[한줄 편집기 보이기]
  //{
      //[2012.09.21.금][추가!!!]{----------------
      //편집기 가운데 [한줄 편집기] 를 보여준다.
      //}----------------------------------------

      _dbgView_Edit->_Width(this->Width - 13 - d_gutter_width - 5);
      _dbgView_Edit->Left = d_gutter_width - 1 + 5;
      _dbgView_Edit->Top  = this->Height/2 - _dbgView_Edit->Height/2;
      _dbgView_Edit->_EDIT_TextOut("");

      //보이기.
      _dbgView_Edit->Visible = true;

  //}

  //[촛점 맞추기]
  //{
      //[2012.09.23.일][추가!!!]{---------------------------------
      //바로 검증식을 작성할수 있도록 [한줄 편집기] 에 촛점 설정.
      //}---------------------------------------------------------

      _dbgView_Edit->SetFocus();

  //}

}

void __fastcall Teditor_edit_Form::_DbgView_ExpStr_Add(void)
{
  //[2012.09.19.수][생성!!!]{--------------------------------------------------
  //[검증식 한줄 편집기<_dbgView_Edit>] 안의 문자열을 [검증식 보기창] 에 등록.
  //
  //<filelistindex> 와 <funcrecindex> 를 모두 구해서 정리해 주어야 한다.
  //
  //처리가 복잡하므로 별도의 함수를 사용하여 처리한다.
  //}--------------------------------------------------------------------------

  //[VAR]
  //{
      struct DBGEXP_TREE_INFO  info;

      //[2011.07.18.월][추가!!!]
      //추가된 [검증식] 의 항목위치.
      int  expItemIndex;

  //}

  //[버튼 동작 대기열 등록]
  //{
      //[2011.07.18.월][중요추가!!!]{------------------------------
      //현재 <ACK> 를 확인하고 있는 중일수 있으므로 이경우는 바로
      //동작되지 않고 일단 [동작 대기열] 에 등록해 놓은뒤에
      //<ACK> 확인용 [타이머] 가 종료되면 자동으로 동작되게 한다.
      //
      //[참고!!!]--------------------------------------------------
      //원래 [검증버튼] 을 위한 것이었으나 실제 [맷돌] 을 대상으로
      //처리하는 과정은 동일하므로 같은 방법을 적용한다.
      //}----------------------------------------------------------

      if(main_Form->timeOut_Timer->Enabled == true)
      {
        main_Form->BtnQueue_Event = _DbgView_ExpStr_Add;
        main_Form->btnQueue_Timer->Enabled = true;
        return;

      }

  //}

  //[초기화]
  //{
      DbgExpTreeInfo_Format(&info);

  //}

  //[검증식 추가정보 만들기]
  //{
      //오류가 발생한 경우는 바로 종료한다.
      if(DbgExpTreeInfo_Make_AddInfo_Edit(&info) != true) return;

  //}

  //[<검증식 정보창> 에 추가]
  //{
      //[2011.07.18.월][수정!!!]
      //추가된 [검증식 항목위치] 를 얻는다.
      //여기서는 이미 [검증식 정보창] 에 정보를 추가하였으므로 바로 종료하지 않고
      //[다시 그려주는 부분] 으로 이동해야 한다.
      if(Ide_Tree_DbgExp_Add(&info, &expItemIndex) != true) goto lbEnd;

  //}

  //[계산]
  //{
      //[!]{----------------------------
      //추가한 다음에 한번 계산해 준다.
      //}-------------------------------

      //추가한 [검증식 항목위치] 를 넘겨준다.
      //여기서는 이미 [검증식 정보창] 에 정보를 추가하였으므로 바로 종료하지 않고
      //[다시 그려주는 부분] 으로 이동해야 한다.
      if(DbgExpTree_View(expItemIndex) != true) goto lbEnd;

  //}

  lbEnd:

  //[표시]
  //{
      //tree 를 한번 그려준다.
      //if(tree_tree_Form->_tree_select_index == d_TREE_dbgExp)
      //{
          //[2011.07.22.금][추가!!!]{----------------------------------------------
          //반드시, [검증식 보기창] 이 보이는 경우만 처리한다.
          //이는 [동작대기열] 에 등록된 경우는 이미 다른 [Tree] 가 보이는 상태에서
          //[검증식 보기창] 이 그려질수 있기 때문이다.
          //}----------------------------------------------------------------------

          //tree_tree_Form->_TreeView(d_TREE_dbgExp, false);

      //}

      //강제로 [검증식 보기창] 으로 전환하면 자연스럽게 다시 그려져 반영된다.
      ide_tree_Form->_tabs_Form->_TabIndex(d_TREE_dbgExp);

  //}

}

void __fastcall Teditor_edit_Form::_EVENT_KeyEnter_dbgView_Edit(void)
{
  //[2012.09.21.금][생성!!!]{--------------
  //[검증식 문자열] 검증창에 추가.
  //
  //[2012.09.23.일][추가!!!]---------------
  //처리후 반드시 [한줄 편집기] 를 감춘다.
  //}--------------------------------------

  //[검증식 문자열 추가]
  //{
      //[검증식 문자열] 추출/추가는 전용 함수로 처리.
      _DbgView_ExpStr_Add();

  //}

  //[감추기]
  //{
      //[2012.09.23.일][추가!!!]
      _dbgView_Edit->Visible = false;

  //}

}

void __fastcall Teditor_edit_Form::_EVENT_KeyDown_Esc_dbgView_Edit(void)
{
  //[2012.09.21.금][생성!!!]{----
  //[검증식 한줄 편집기] 감추기.
  //}----------------------------

  if(_dbgView_Edit != NULL)
  {
    if(_dbgView_Edit->Visible == true) { _dbgView_Edit->Visible = false; }

  }

}

//---------------------------------------------------------------------------------
//[부가함수]-----------------------------------------------------------------------
//---------------------------------------------------------------------------------

void __fastcall Teditor_edit_Form::InfoTree_Call(//[2012.05.30.수][추가!!!]
                                                 //<Parser()> 를 돌리지 않고 [재정리] 만 하는 경우는 <true>.
                                                 //이는 [단어조합중] 인 경우 계속 [근접단어] 를 찾을때 사용.
                                                 //즉, 이미 정리된 {DB} 정보만 가지고 계속 처리하는 경우.
                                                 bool  pInfoSetOnly)
{
  //[2012.04.15.일][생성!!!]{----------------------------------
  //[실시간 선언정보판] 을 현재 [입력지정자] 가위 치한 단어의
  //가장 처음아래에 보여준다.
  //
  //단, 먼저 아래 두가지를 처리해야 한다.
  //1) [실시간 선언정보] 얻기.
  //2) 선언정보를 [실시간 선언정보판] 에 정리.
  //
  //[2012.05.27.일][수정!!!]-----------------------------------
  //[2012.05.30.수][수정!!!]-----------------------------------
  //[2012.05.31.수][수정!!!]-----------------------------------
  //이 함수는 [근접단어정렬] 의 경우가 아닌 [기본보기] 에서는
  //<Ctrl+Space> 호출시 한번만 동작되어야 한다.
  //이는 처리가 복잡하고 시간이 많이 걸리기 때문에 [편집기] 의
  //다른 동작에 무리를 준다.
  //
  //[2012.06.03.일][수정!!!]-----------------------------------
  //[2012.06.22.금][수정!!!]-----------------------------------
  //}----------------------------------------------------------

  //[VAR]
  //{
      class DATABASE  *DB_;

      int  wordStartIndex;

      //[2012.05.21.월][추가!!!]
      int  wordEndIndex;

      int  posX, posY;

      //[2012.05.22.화][추가!!!]
      char  word[1024];

      //[2012.06.01.금][추가!!!]
      //처음에는 [다시 그리기] 된 것이 없는 것으로 초기화.
      bool  rePainted = false;

  //}

  //[DB 위치 얻기]{------
  DATABASE_GetPtr(&DB_);
  //}--------------------

  //[존재확인]
  //{
      //[선언정보판] 이 존재하지 않는다면 처리하지 않는다.
      if(info_tree_Form == NULL) goto lbEnd;

  //}

  //[실시간 선언정보 얻기]
  //{
      //[2012.05.10.목][수정!!!]{-------------------------------------
      //[입력지정자 위치] 정보를 전달.
      //이는 [실시간 선언정보 수집] 중 [입력지정자] 가 위치한 함수의
      //영역정보를 자세하게 얻기 위한것.
      //
      //[2012.05.29.화][수정!!!]--------------------------------------
      //[새설계묶음] 이나 [설계묶음] 이 없이 일반 문서가 열려있는경우
      //기본적으로 <Ide_RealTimeInfo()> 함수 안에서 [새설계묶음] 에
      //걸려서 <flase> 가 된다.
      //이 경우는 다음 단계에서 [실시간 선언 정보판] 이 나오지 않도록
      //더이상 처리하지 않고 종료해야 한다.
      //}--------------------------------------------------------------

      if(pInfoSetOnly != true)
      {
        //[2012.05.30.수][수정!!!]{------------------
        //[재정리] 만 하는 경우는 처리하지 않는다.
        //처음 <Ctrl+Space> 로 보일때만 [한번] 처리.
        //}------------------------------------------

        //[참조 연산자 위치 임시 지정]
        //{
            //[2012.06.22.금][추가!!!]{------------------------------------------------------------
            //유효한 [단어] 위치와 정확한 "->", "." [연산자] 위치를 알기 위하여 아래에서
            //<Get_IndexWord()> 함수를 구동하는데 이 함수는 [정의이름] 을 반영하여 처리하므로
            //반드시 먼저 <Parser()> 를 처리해야 하고, 이를 처리하는 <Ide_RealTimeInfo()> 함수를
            //먼저 처리해야 한다.
            //
            //문제는 <Ide_RealTimeInfo()> 함수를 처리할때 "->", "." 의 [모체:선언형] 을 얻기 위한
            //[식:시작위치] 를 얻는다는 점이고, 이를 위하여 해당 "->", "."  [연산자] 위치를 먼저
            //지정해야 한다는 점이다.
            //
            //그러나, 정확한 위치를 알수 있는 <Get_IndexWord()> 함수는 나중에 실행된다.
            //
            //따라서, <Ide_RealTimeInfo()> 함수를 실행전 일단 "->", "." [연산자] 위치 대신
            //현재 [입력지정자] 위치를 지정해 준다.
            //
            //이는 [구성원] 앞에 바로 "->", "." 연산자가 있다는 가정이라면 "->", "." 를 포함하는
            //[식:시작위치] 는 "같기" 때문이다.
            //
            //[주의!!!]----------------------------------------------------------------------------
            //즉, 현재 [입력지정자] 가 위치한 [식:시작위치] 는 항상 구하는 셈이다.
            //
            //[중요!!!][2012.06.24.일]*************************************************************
            //<Get_IndexWord()> 함수는 [정의이름] 을 처리할 필요가 없어졌으므로 <GetNextWord()> 를
            //사용하는 것으로 수정하여 굳이 이 위치에서 먼저 <Ide_RealTimeInfo()> 를 처리할 필요는
            //없어졌으나
            //
            //아래 <DB_->FILELIST_GetIndex_WithName()> 함수를 사용하는데 {DB} 가 채워져 있어야
            //처리 가능하므로 <Ide_RealTimeInfo()> 를 먼저 처리해야 한다.
            //}------------------------------------------------------------------------------------

            //일단, 가설정으로 현재 입력지정자 위치를 기록.
            DB_->RtExpMark_OperatorIndex(_caretindex);

        //}

        //[실시간 선언 정보 수집]
        //{
            if(Ide_RealTimeInfo(_textinfo[_textinfo_index].filename.c_str(),
                                //[2012.05.10.목][추가!!!]
                                _caretindex) != true) goto lbEnd;

        //}

        //[일반/참조연산자 구분 정보 얻기]
        //{
            //[2012.06.19.화][추가!!!]{------------------------------------------------------------
            //<Ctrl+Space> 에 해당하는 두 경우를 구분하여 처리.
            //
            //1) 현재 [입력지정자] 앞의 단어가 "->", "." 인 경우.
            //   => [모체 선언형] 을 알기 위하여 "->", "." 이 포함된 [식:시작위치] 를 찾는다.
            //   => [모체 선언형] 에 해당하는 [항목] 을 찾고 [구성원] 을 보여준다.
            //   즉, 두단계로 구분하여 처리.
            //
            //2) 1) 이외는 모두 일반 [실시간 선언정보 보기] 의 경우.
            //   => 이미 처리되고 있다.
            //
            //[2012.06.22.금][중요수정!!!]---------------------------------------------------------
            //[현재 입력지정자 앞] 만 따지지 않고 [현재 단어 앞 단어] 가 "->", "." 인 경우를 처리.
            //이는 [구성원] 의 어디에 [입력지정자] 가 있더라도 항상 정확한 [모체] 를 찾아서
            //해당 항목을 찾아 주어야 하기 때문이다.
            //
            //[참고!!!]----------------------------------------------------------------------------
            //이를 위하여 <Get_IndexWord()> 함수 제작.
            //}------------------------------------------------------------------------------------

            //[현재단어/앞단어 추출]
            //{
                //[2012.06.22.금][추가!!!]

                //[문서 정보 설정]
                //{
                    //[!]{-------------------------------------------------------------------------
                    //<Get_IndexWord()> 함수를 사용하기 전에 반드시 <{DB}:parserinfo> 정보를 설정.
                    //}----------------------------------------------------------------------------

                    //현재 [열려있는 문서] 처음부터 처리하는 것이므로 반드시 초기화.
                    DB_->PARSERINFO_Format(&(DB_->parserinfo));

                    //현재 문서 등록.
                    DB_->parserinfo.buf = _editbuf;

                    //현재 문서 크기 지정.
                    //이는 <Get_NextWord()> 함수 처리시 내부적으로 문서의 크기를 알아야 종료하기 때문이다.
                    DB_->parserinfo.filesize = _filesize;

                    //현재 처리하는 문서의 [문서번호] 를 설정.
                    //<Get_IndexWord()> 안에서 [정의이름] 까지 반영하여 처리하는데
                    //이때 유효한 [정의이름] 을 걸러내는데 반드시 필요.
                    DB_->FILELIST_GetIndex_WithName(_textinfo[_textinfo_index].filename.c_str(),
                                                    &(DB_->parserinfo.filelistindex));

                    //[2012.06.23.토][추가!!!]{-----------------------------------------------
                    //현재 [입력지정자] 위치가 [주석문] 안 인지 등을 알기 위하여 [위지 지정].
                    //<GetNextWord()> 나 <GetNextWordAll()> 함수에서 자동 처리.
                    DB_->parserinfo.setIndex = _caretindex;
                    //}-----------------------------------------------------------------------

                //}

                //[단어 추출]
                //{
                    //[!]{-----------------------------------------------------------------------------
                    //현재 단어정보와 이전 단어 추출시 문제가 있거나 추출하지 못했다면 더이상
                    //처리하지 않는다.
                    //
                    //[중요!!!]------------------------------------------------------------------------
                    //만일 현재 [입력지정자] 가 존재하는 위치에 단어가 없는 경우는 처리하지 않고 종료.
                    //단, [문자열], [문자상수] 안에 존재하는 경우는 여기서 종료되지 않기 때문에
                    //다음 단계에서 구분처리한다.
                    //
                    //[주의!!!][2012.06.24.일]---------------------------------------------------------
                    //<Get_IndexWord()> 함수 반환이 <false> 인 경우라도 반드시 현재 [입력 지정자] 위치
                    //[단어] 가 [주석문] 안에 있다는 의미는 아니다.
                    //
                    //"[단어] ...[공백(현위치)]... [단어]" 인 경우도 현 위치에 [단어] 가 존재하지 않아
                    //<false> 가 반환될수 있기 때문이다.
                    //
                    // 금일 <Get_IndexWord()> 함수는 [정의이름] 을 반영하지 않고 있는 그대로 처리하는
                    //<GetNextWord()> 함수를 사용하는 것으로 내부적으로 수정되었음.
                    //}--------------------------------------------------------------------------------

                    if(Get_IndexWord(_caretindex, word, &wordStartIndex) != true) goto lbEnd;

                //}

                //[단어 유효 판별]
                //{
                    //[!]{------------------------------------------------------------------------
                    //[주석] 등 안에 존재하는 경우는 위에서 자동 [무효] 처리 되므로
                    //여기서는 [문자열], [문자상수] 안에 존재하는 경우만 [무효] 처리한다.
                    //이를 구분할수 있는 [판별정보] 는 <Get_IndexWord()> 함수를 처리할때
                    //<{DB}:parserinfo> 안에 정리돼 있다.
                    //
                    //[2012.06.23.토][추가!!!]----------------------------------------------------
                    //[묶음주석], [한줄주석] 의 경우도 추가.
                    //<DB_->parserinfo.setIndex> 설정 위치는 위에서 [입력지정자:위치] 로 설정.
                    //이 위치가 [주석문] 안인 경우는 [무효영역] 으로 간주 [실시간 선언 정보판] 을
                    //보이지 않는다.
                    //<struct PARSERINFO> 안 설명 참고.
                    //
                    //<GetNextWord()> 등 함수는 [주석문] 안은 아예 [단어] 를 추출하지 않기 때문에
                    //별도로 이를 검사할 필요가 있기 때문에 부가 정보가 필요.
                    //}---------------------------------------------------------------------------

                    //현재 [단어] 가 [문자열], [문자상수], [주석문] 안에 존재한다면 [실시간 선언 정보보기] 의
                    //대상이 될수 없기 때문에 여기서 종료.
                    if((DB_->parserinfo.what_in   == 'c') || (DB_->parserinfo.what_in   == 's') ||
                       //[2012.06.23.토][추가!!!]
                       //<DB_->parserinfo.setIndex> [지정:위치] 가 [주석문] 안인가?
                       (DB_->parserinfo.setWhatIn == 'r') || (DB_->parserinfo.setWhatIn == 'h'))
                    {
                      goto lbEnd;

                    }

                //}

            //}

        //}

        //[판별]
        //{
            //[2012.06.22.금][전부수정!!!]{-----------------------------------------
            //위에서 얻은 정보를 바탕으로 [일반/참조 연산자] 중 어떤 경우인지 구분.
            //<Get_IndexWord()> 에서 얻은 [앞:단어] 로 쉽게 구분 가능.
            //
            //[주의!!!]*************************************************************
            //이미 위의 <Ide_RealTimeInfo()> 함수에서 <{DB}:_rtExpMark> 관련 정보를
            //얻었으므로 기존 정보가 [초기화] 되는 것을 막기 위하여 여기서는
            //
            //<RtExpMark_OperatorIndex()> 함수를 사용하지 않고 직접 할당.
            //}---------------------------------------------------------------------

            if(STR_Match(word, "->") || STR_Match(word, "."))
            {
              //[!]{--------------------------------------------------------
              //이 경우는 [현재 단어] 는 [구성원] 가능성이 있는 것으로 보고
              //[참조 연산자] 관련 정보로 처리.
              //}-----------------------------------------------------------

              DB_->_rtExpMark.opIndex = wordStartIndex;
              //이미 위에서 얻어진 [정보] 가 초기화 되지 않도록 절대 사용 금지.
              //DB_->RtExpMark_OperatorIndex(wordStartIndex);

              //[연산자 길이]
              //{
                  //[2012.06.23.토][추가!!!]{-------------------------------------
                  //연산자 단어길이를 기록.
                  //
                  //아래 <Ide_InfoTree_Operator()> 함수에서 [식] 을 추출할 공간을
                  //[동적생성] 하는데 정확한 크기를 알기 위하여 필요.
                  //[연산자] 까지 [식] 으로 추출되나 [연산자 위치] 정보만으로는
                  //[연산자 길이] 를 알수가 없기 때문에 [길이] 정보가 필요.
                  //}-------------------------------------------------------------

                  DB_->_rtExpMark.opLength = STR_Length(word);

              //}

            }
            else
            {
              //[구성원] 정보 조건에 해당하지 않는다면 <-1> 로 [일반 정보 보기] 로 설정.
              DB_->RtExpMark_OperatorIndex(-1);

            }

        //}

        //[참조 연산자 관련 처리]
        //{
            //[2012.06.21.목][추가!!!]{--------------------------------
            //"->", "." 연산자 [모체:선언형] 관련 부가 처리를 수행.
            //현재 [입력지정자] 앞의 단어가 "->", "."  인 경우가 해당.
            //이미 위에서 [판별] 되었다.
            //}--------------------------------------------------------

            if(DB_->_rtExpMark.opIndex >= 0)
            {
              //[!]{---------------------------------------------------
              //이 경우는 "->", "." 연산자의 [모체:선언형] 정보를 얻어
              //해당 [구성원] 을 보여주는 관련 처리를 수행.
              //}------------------------------------------------------

              //[함수 영역 정보 설정]
              //{
                  //[!]{------------------------------------------------
                  //바로 위에서 <Ide_RealTimeInfo()> 를 처리시 자동으로
                  //얻어진 [함수 영역 정보] 를 기록.
                  //}---------------------------------------------------

                  DB_->_rtExpMark.funcRecIndex = DB_->_rtDefInfoEtc.funcRecIndex;

              //}

              //[참조 연산자 포함 [식] 처리]
              //{
                  //[!]{-----------------------------------------------------------------------------
                  //<Ide_RealTimeInfo()> 를 처리하면서 "->", "." 앞의 [모체:선언형] 을 알수 있는
                  //[식:시작위치] 를 얻었으므로 이 위치의 [식] 을 처리하여 [모체:선언형] 을 얻는다.
                  //
                  //[2012.06.23.토][중요수정!!!]-----------------------------------------------------
                  //[검증식] 처럼 [식] 부분을 따로 떼어낸뒤 처리한다.
                  //이는 [미완성식] 인 경우도 확실하게 처리하기 위한것.
                  //자세한 수정 내용은 <Ide_InfoTree_Operator()> 함수안 설명 참고.
                  //
                  //<Ide_InfoTree_Operator()> 함수 안에서 <DB_->_rtExpMark.opIndex> 정보는
                  //[식:시작위치] 를 기준으로 한 [추가위치] 로 변경된다.
                  //이는 [식] 을 별도 문자열로 추출하여 처리하기 때문.
                  //아래에서 <DB_->_rtExpMark.opIndex> 정보는 사용하지만 <-1> 만 아니면 되므로 무관.
                  //}--------------------------------------------------------------------------------

                  //[식] 처리시 오류가 있는 경우는 [실시간 선언 정보판] 을 보이지 않고 바로 종료.
                  if(Ide_InfoTree_Operator() != true) goto lbEnd;

              //}

            }

        //}

      }

  //}

  //[선언정보판에 선언정보 정리]
  //{
      //[정보창:설계정보]
      //{
          //[2012.05.27.일][추가!!!]{--------------------------------------------------
          //[정보창:설계정보] 와 [실시간 선언 정보판] 은 같은 <Parser()> 를 사용하고
          //같은 {DB} 에 정보가 정리된 것을 사용하므로 [실시간 선언 정보] 를 수집한뒤
          //반드시 [정보창:설계정보] 에도 정리해 준다.
          //
          //이는 [2중선택] 시 [선언위치] 를 찾는데 {DB} 정보를 사용하기 때문이며
          //항상 가장 마지막에 정리된 {DB} 정보를 사용해야 하기 때문이다.
          //
          //단, <Ctrl+Space> 를 사용하여 [실시간 선언 정보 수집] 의 경우를 제외하고는
          //[정보창:설계정보] 만 보이고 때문에 [실시간 선언 정보판] 은 보이지 않으므로
          //[실시간 선언 정보판] 을 재정리 할 필요는 없다.
          //
          //[실시간 선언 정보판] 은 보이기 전에 반드시 <Parser()> 를 처리하고 {DB} 를
          //정리하므로 이런 [비동기] 오류를 고려할 필요가 없다.
          //}--------------------------------------------------------------------------

          if(pInfoSetOnly != true)
          {
            //[2012.05.30.수][수정!!!]{----------------------------------------------
            //[재정리] 만 하는 경우는 처리하지 않는다.
            //[실시간 선언 정보판] 은 <Ctrl+Space> 로만 보여지고, 이때 반드시 한번은
            //처리 되므로 [재정리] 시에는 중복 처리하지 않는다.
            //}----------------------------------------------------------------------

            Ide_TreeInfo();

          }

      //}

      //[<근접단어정렬> 구분 처리]
      //{
          if(_ide_option->editorInfoTree_ClosedWord == true)
          {
            //[2012.05.30.수][추가!!!]{---------------------------------------------
            //[근접단어정렬] 인 경우는 현재 [입력 지정자 위치 단어] 전체가 아니라
            //이 단어에서 [입력지정자] 까지의 [단어] 만 추출하여 사용.
            //이는 [가장가까운단어] 를 계속 찾아서 [목록] 방식으로 보여주기 위한것.
            //}---------------------------------------------------------------------

            //[현재 입력 지정자 위치 단어 얻기]
            //{
                //[2012.05.30.수][추가!!!]{--------------
                //[근접단어정렬] 을 위한 [단어] 를 추출.
                //}--------------------------------------

                STR_Get_WordBound(_editbuf, _filesize, _caretindex,
                                  &wordStartIndex,
                                  &wordEndIndex);

                //[입력 지정자 위치까지의 단어 얻기]
                //{
                    //[2012.05.30.수][추가!!!]{-----------------------------------
                    //현재 입력 지정자 위치에 '\0' 을 넣으면 완성된다.
                    //이미 [입력지정자] 는 [한글] 의 경우도 한문자로 간주하도록
                    //처리되므로 바로 사용해도 안전하다.
                    //
                    //가장 확실하게 <STR_SubString()> 함수를 사용하여 처리.
                    //
                    //[주의!!!]---------------------------------------------------
                    //[공백] 이나 [연산자] 사이 등인 경우는 [단어] 가 "" 상태다.
                    //<wordStartIndex == wordEndIndex> 인 상태.
                    //
                    //이 경우는 [전체정보] 보이기로 처리해야 한다.
                    //
                    //<Ide_InfoTree_SetInfo()> 자체적으로 "" 인 경우는 자동적으로
                    //[근접단어정렬] 을 사용하지 않는 것으로 처리된다.
                    //}-----------------------------------------------------------

                    STR_SubString(_editbuf,
                                  wordStartIndex, _caretindex - wordStartIndex,
                                  word);

                //}

            //}

            //[근접단어정렬]
            //{
                //[참고!!!]{---------------------------------------------------
                //조건에 따라 [근접단어정렬] 방식으로 정리.
                //<word == ""> 인 경우는 내부에서 자동적으로 [근접단어정렬] 을
                ///사용하지 않고 [전체수집] 으로 처리된다.
                //}------------------------------------------------------------

                Ide_InfoTree_SetInfo(//[2012.05.29.화][추가!!!]
                                     //[전체수집] 을 사용.
                                     word,
                                     //[2012.05.30.수][추가!!!]
                                     DB_->_rtDefInfoEtc.funcRecIndex,
                                     //[2012.06.01.금][추가!!!]
                                     //여기서는 [다시 그리기] 하지 않는다.
                                     false);

            //}

          }
          else
          {
            //[2012.05.30.수][수정!!!]{-----------------------------------
            //[근접단어정렬] 방식이 아니라 [전체수집] 방식으로 일반 처리.
            //}-----------------------------------------------------------

            Ide_InfoTree_SetInfo(//[2012.05.29.화][추가!!!]
                                 //[전체수집] 을 사용.
                                 NULL,
                                 //이 [함수영역정보] 는 이 경우 의미 없다.
                                 DB_->_rtDefInfoEtc.funcRecIndex,
                                 //[2012.06.01.금][추가!!!]
                                 //여기서는 [다시 그리기] 하지 않는다.
                                 false);

          }

      //}

  //}

  //[선언정보판:보이기]
  //{
      //[함수 안인가?]
      //{
          //[2012.05.10.목][추가!!!]{------------------------------------------
          //[함수정보] 를 얻지 못했다면 표시하지 않는다.
          //
          //[2012.05.23.수][설명!!!]-------------------------------------------
          //단, 이 경우 <*.h> 나 다른 문서의 경우는 [정보판] 이 나오지 않는다.
          //[정보판] 은 [이미 선언된 자료의 사용] 에 목적이 있으므로 [선언부]
          //에서 보일 필요는 없다.
          //}------------------------------------------------------------------

          if(DB_->_rtDefInfoEtc.funcRecIndex == -1)
          {
            if(info_tree_Form->Visible == true) { info_tree_Form->Visible = false; }

            goto lbEnd;

          }

      //}

      //[단어 시작 위치 얻기]
      //{
          //[2012.05.21.월][수정!!!]{-----------------------------------------------------------
          //<Str_Get_WordBoundStart()> 함수는 [시작위치] 만 검출하지만 이 경우
          //[단어] 가 아닌 [공간] 에 위치하는 경우는 [입력지정자] 위치가 반환된다.
          //즉, [단어] 가 없음에도 위치가 반환되어 정확한 정보를 얻을수 없다.
          //
          //따라서, [단어:시작/끝 위치] 정보를 정확하게 알수 있는 <STR_Get_WordBound()>
          //함수를 사용한다.
          //
          //[단어:시작 위치] 와 [단어:끝 위치] 가 [같다] 면 이는 [단어 없음] 으로 볼수 있다.
          //
          //이 [정의] 는 [단어] 위치가 아닌 [공백/주석] 등의 공간에서 <Ctrl+Space> 를 누른 경우
          //[실시간 정보 수집] 후 현재 [입력 지정자] 가 위치한 [함수] 를 <Tree> 상에서 열어줄때
          //반드시 필요하다.
          //}-----------------------------------------------------------------------------------

          //wordStartIndex = Str_Get_WordBoundStart(_editbuf, _filesize, _caretindex);
          //[2012.05.21.월][추가!!!]
          STR_Get_WordBound(_editbuf, _filesize, _caretindex,
                            &wordStartIndex,
                            &wordEndIndex);

      //}

      //[표시 위치 얻기]
      //{
          InfoTree_Cal_XY(wordStartIndex, &posX, &posY);

      //}

      //[선택 단어가 있나?]
      //{
          //[2012.05.21.월][추가!!!]{-------------------------------------------------
          //현재 [입력 지정자] 위치에 [단어] 가 없고 [공간] 상이라면
          //[입력 지정자] 가 위치한 [함수] 를 <infoTree> 가장 위치에 보여주고
          //[+] => [-] 로 열어서 정보를 보여준다.
          //즉, [현재 함수 알기] 기능으로 실제 꼭 필요한 기능이다.
          //
          //[단어:시작/끝 위치] 가 같다면 [공간] 상에 위치하는 것으로 본다.
          //
          //[주석]. [문자열], [문자상수] 안도 [무효공간] 으로 본다.
          //[실시간 선언 정보판] 안에 보여줄 정보가 없다.
          //
          //[2012.06.22.금][중요수정!!!]----------------------------------------------
          //"구조체.|" 인 경우("|" 는 입력지정자)는 [단어] 가 없더라도 사용 가능한
          //해당 [구조체] 의 [구성원] 정보를 보여주어야 한다.
          //이미 위에서 [앞 단어] 가 "->", "." 인 경우는 <DB_->_rtExpMark.opIndex> 에
          //해당 연산자 위치가 기록되어 현재 [구성원] 정보 요청임을 알수 있다.
          //}-------------------------------------------------------------------------

          if((wordStartIndex == wordEndIndex) &&
             //[2012.06.22.금][추가!!!]
             //[구성원] 정보 요청이 아닌 경우만 해당.
             (DB_->_rtExpMark.opIndex == -1))
          {
            //[!]{----------------------------------------------------------------------
            //이 경우는 [단어] 가 없는 공간에서 보여지는 경우.
            //[함수 영역] 정보를 얻기 위한 것으로 찾은 [함수 항목] 을
            //[+] => [-] 로 열어주고 보이는 첫 위치로 이동.
            //
            //[2012.05.28.월][설명!!!]--------------------------------------------------
            //<if(wordStartIndex == wordEndIndex)> 조건인 경우 [현재 함수영역 정보] 를
            //보여주게 되므로 <Tinfo_tree_Form::_Show()> 함수 안에서 이 조건을 감지하고
            //[아래 귀뜸말] 에 [함수영역정보] 임을 알려주는 문자열을 추가하게 된다.
            //}-------------------------------------------------------------------------

            rePainted = info_tree_Form->_TitleView_Func_DbRecIndex(DB_->_rtDefInfoEtc.funcRecIndex);

          }
          else
          {
            //[2012.05.22.화][추가!!!]{---------------------------------------
            //[단어] 가 있는 경우 [단어] 에 해당하는 정보를 가장 위에 보이기.
            //
            //[변수], [정의이름], [사용함수] 등 사용 정보가 해당.
            //[지역변수] 의 경우는 <DB_->_rtDefInfoEtc.funcRecIndex> 정보로
            //자동 구분된다.
            //
            //[2012.06.24.일][설명!!!]----------------------------------------
            //"->, "." 대상 [구성원] 정보 처리는 <_TitleView_Word()> 함수에서
            //조건을 비교하여 자동 처리된다.
            //}---------------------------------------------------------------

            //[단어 추출]
            //{
                STR_SubString(_editbuf,
                              wordStartIndex, wordEndIndex - wordStartIndex,
                              word);

            //}

            //[단어] 에 해당하는 항목 지정.
            rePainted = info_tree_Form->_TitleView_Word(DB_->_rtDefInfoEtc.funcRecIndex, word);

          }

      //}

      //[표시]
      //{
          //[감추기 관련 정보 제공]
          //{
              //[2012.05.23.수][추가!!!]{----------------------------------------
              //[정보판] 의 [감출 시점] 은 [편집기] 상태와 관련이 있으므로
              //[편집기] 에서 [정보판] 을 호출할때 사전에 미리 설정해 준다.
              //
              //이는 처음 [단어 구간] 을 입력지정자가 벗어난 경우 [단어 지정] 을
              //[해제] 하고 [정보판] 을 [감추기] 하는데 이 정보를 사용하기 때문.
              //}----------------------------------------------------------------

              info_tree_Form->_edit_WordIndexS = wordStartIndex;
              info_tree_Form->_edit_WordIndexE = wordEndIndex;

              //[2012.05.25.금][추가!!!]{----------------------------------------------------
              //현재 [대상 단어] 행 정보 저장.
              //[화면지정자] 로 [다른 단어] 지정시 [이전 단어] 를 [해제] 시키기 위하여 필요.
              //
              //반드시 여기서 [한번만] 처리되어야 한다.
              //}----------------------------------------------------------------------------

              info_tree_Form->_edit_Row = _row;

              //[2012.06.01.금][추가!!!]{--------------------------------------------
              //<Ctrl+Space> 로 처음 나온 경우는 반드시 [초기화] 한다.
              //
              //[2012.06.01.금][수정!!!]---------------------------------------------
              //단, "A|B" 에서 처음 보인 뒤 "|AB" 로 [입력지정자] 가 이동하는 경우
              //여기서 "" 로 초기화 하면 "|AB" 시점에서 역시 "" 이 되어
              //[같은 단어] 로 보아 <Tinfo_tree_Form::_AutoHide_WordBound()> 에서
              //[재정리] 처리를 하지 않게 된다.
              //따라서, 아예 초기에 [단어] 로 사용할수 없는 [연산자] 로 초기화 한다.
              STR_Assign(info_tree_Form->_edit_Word, "*");
              //
              //[함수사용제어] 용으로 반드시 <Ctrl+Space> 로 보이는 경우는 <true> 로
              //초기화 해야 한다.
              info_tree_Form->_sw_AutoHide_WordBound = true;
              //}--------------------------------------------------------------------

          //}

          //[투명:해제]
          //{
              //[2012.06.03.일][중요추가!!!]{--------------------------------------------------
              //[실시간 선언 정보판] 이 [투명] 으로 설정돼 있는 경우
              //반드시 [다시 그리기] 전에 먼저 [투명:해제] 시켜야 한다.
              //그렇지 않은 경우 [다시 그리기] 때에 다 그려지지 않고
              //보일때 잔상이 남아 이전것이 잠깐 보였다 다시 그려지는 문제가 있다.
              //속도가 빠를때는 무관하지만 속도가 느린 PC 에서는 잔상이 남게 된다.
              //완전히 다시 그리고 => 보이고 난뒤에 => 다시 재설정 하는 것이 가장 완벽하다.
              //
              //단, 이 부분은 <InfoTree_Call()> 사용시만 반영되고 계속 보이는 상태에서 처리되는
              //<InfoTree_ReCall()> 에서는 반영할 필요가 없다.
              //[안보이다] => [보이는] 경우에만 해당하는 내용이기 때문.
              //}-------------------------------------------------------------------------------

              info_tree_Form->AlphaBlend = false;

          //}

          //[다시 그리기]
          //{
              //[2012.06.01.금][추가!!!]{--------------------------------------------
              //<_TitleView_Func_DbRecIndex()> 나 <_TitleView_Word()> 함수에서
              //[다시 그리기] 가 처리되지 않았다면 여기서 한번만 [다시 그리기] 한다.
              //
              //[2012.06.03.일][주석처리!!!]-----------------------------------------
              //보이기 전에 다시 그리도록위치를 <_Show()> 이전으로수정.
              //}--------------------------------------------------------------------

              if(rePainted != true)
              {
                //내용만 다시 그리므로 폼을 잘라내지 않는다.
                info_tree_Form->_TreeView(false, false);

              }

          //}

          //[보이기]
          //{
              //[단어 지정] 까지 자동으로 내부 처리.
              info_tree_Form->_Show(main_Form->Left + ide_editor_Form->Left + posX,
                                    main_Form->Top + ide_editor_Form->Top + editor_edit_Form->Top + posY);

          //}

          //[투명:재설정]
          //{
              //[2012.06.03.일][중요추가!!!]{----------------------------------------------------
              //반드시 [다시 그리기] 되고 [보이기] 된 뒤에 [재설정] 해야 한다.
              //그래야 잔상으로 인한 깜박임이 없어 보기 좋다.
              //[설정] 을 반영하여 [재설정] 한다(현재 [투명] 속성을 사용하지 않을수도 있으므로).
              //}--------------------------------------------------------------------------------

              info_tree_Form->AlphaBlend = _ide_option->editorInfoTree_AlphaBlend;


          //}

          //[편집기] 에서 계속 편집가능하도록 다시 [촛점] 을 맞춘다.
          if(this->Focused() == false) { this->SetFocus(); }

      //}

      //[대상 단어 지정]
      //{
          //[2012.05.25.금][수정!!!]{----------------------------------------------------
          //<info_tree_Form->_Show()> 함수 안에서 [실시간 선언 정보판] 을
          //보여주고 난 다음 바로 [단어 지정] 을 하므로 여기서는 처리하지 않는다.
          //이는 <info_tree_Form->_Show()> 안에 [귀뜸말] 처리부가 있어서 모두
          //처리하고 난 다음에 [단어지정] 을 하는 경우 약간의 [시간차] 가 발생하기 때문.
          //따라서, <info_tree_Form->_Show()> 함수 안에서 [정보판] 을 보인후 바로
          //[단어지정] 하는 것으로 금일 수정하였다.
          //}----------------------------------------------------------------------------

      //}

  //}

  lbEnd:

//[검증용]
//{
    //[2012.06.20.수][수정!!!]
    //[식:시작위치] 부터 [연산자] 위치까지 지정.
    
    /*
    if((DB_->RtExpMark_Read() + DB_->_rtExpMark.opIndex) >= 0)
    {
      History_SelectX(DB_->RtExpMark_Read(),   //[식] 시작위치.
                      DB_->RtExpMark_Read() + DB_->_rtExpMark.opIndex, //[연산자] 위치.
                      true,
                      NULL,
                      true,
                      false,
                      false);

      Ide_Test(DB_->_rtExpMark.motherTypeListIndex);

      msg_msg_Form->_Print(0, DB_->typelist[DB_->_rtExpMark.motherTypeListIndex].type);

    }
    */



    /*
    //"{" ... [지역변수 선언 영역 끝] 까지 [선택영역] 으로 지정.
    History_SelectX(DB_->_rtDefInfoEtc.areaStartIndex,
                    DB_->_rtDefInfoEtc.localDefEndIndex,
                    true,
                    NULL,
                    true,
                    false,
                    false);
    */

//}

}

void __fastcall Teditor_edit_Form::InfoTree_ReCall(//입력지정자 위치 [전체단어] 시작위치.
                                                   int    pWordIndexS,
                                                   //입력지정자 위치 [전체단어] 끝위치.
                                                   int    pWordIndexE,
                                                   //[입력지정자] 위치까지의 부분단어.
                                                   char  *pPartWord_,
                                                   //<Ide_InfoTree_SetInfo()> 로 재정리 하는 경우는 <true>.
                                                   bool   pSetInfo)
{
  //[2012.06.01.금][생성!!!]{----------------------------------------------------
  //<_AutoHide_WordBound()> 함수에서 [근접단어정렬:재정리] 시에만 호출된다.
  //이를 위하여 <InfoTree_Call()> 함수를 바탕으로 특별하게 만든것.
  //
  //1) <Ctrl+Space> 로 <InfoTree_Call()> 함수가 한번 호출된 뒤에 사용해야 한다.
  //   이 함수는 [실시간 선언 정보판] 이 이미 보이고 있는 상태에서 [단어조합] 이
  //   연속되는 경우만 호출되기 때문.
  //
  //2) [재정리] 에 필요한 최소한의 처리만 수행(처리시간 단축을 위한것).
  //
  //[2012.06.03.일][수정!!!]-----------------------------------------------------
  //[2012.06.24.일][수정!!!]-----------------------------------------------------
  //<InfoTree_Call()> 함수처럼 "->", "." 연산자 [구성원] 정보 보기를 지원.
  //반드시 <InfoTree_Call()> 함수는 한번 처리되고 이때 [구성원] 보기 정보는
  //다 추출돼 있으므로 여기서는 사용만 하면 된다.
  //}----------------------------------------------------------------------------

  //[VAR]
  //{
      class DATABASE  *DB_;

      char  word[1024];

      //[2012.06.01.금][추가!!!]
      //처음에는 [다시 그리기] 된 것이 없는 것으로 초기화.
      bool  rePainted = false;

  //}

  //[DB 위치 얻기]{------
  DATABASE_GetPtr(&DB_);
  //}--------------------

  //[존재확인]
  //{
      //[선언정보판] 이 존재하지 않는다면 처리하지 않는다.
      if(info_tree_Form == NULL) return;

  //}


  //[선언정보판에 선언정보 정리]
  //{
      //[!]{----------------------------------------------
      //반드시 [근접단어정렬:재정리] 상태에서만 사용된다.
      //}-------------------------------------------------

      //[<근접단어정렬> 구분 처리]
      //{
          if(_ide_option->editorInfoTree_ClosedWord == true)
          {
            //[2012.05.30.수][추가!!!]{---------------------------------------------
            //[근접단어정렬] 인 경우는 현재 [입력 지정자 위치 단어] 전체가 아니라
            //이 단어에서 [입력지정자] 까지의 [단어] 만 추출하여 사용.
            //이는 [가장가까운단어] 를 계속 찾아서 [목록] 방식으로 보여주기 위한것.
            //}---------------------------------------------------------------------

            //<_AutoHide_WordBound()> 함수에서 [부분단어] 는 인수로 전달해 주지만
            //[전체단어] 는 구해서 전달하지 않고 [범위] 만 전달 하므로 [전체단어] 는 직접 구한다.

            //[근접단어정렬]
            //{
                //[참고!!!]{---------------------------------------------------
                //조건에 따라 [근접단어정렬] 방식으로 정리.
                //<word == ""> 인 경우는 내부에서 자동적으로 [근접단어정렬] 을
                ///사용하지 않고 [전체수집] 으로 처리된다.
                //}------------------------------------------------------------

                if(pSetInfo == true)
                {
                  //[!]{----------------------------------------------------------
                  //[재정리] 를 요청한 경우만 사용한다.
                  //<_AutoHide_WordBound()> 함수에서 [단어 미변경] 시에는
                  //[재정리] 할 필요는 없으나 [부가처리] 는 해야하는 경우도 있다.
                  //}-------------------------------------------------------------

                  Ide_InfoTree_SetInfo(pPartWord_, DB_->_rtDefInfoEtc.funcRecIndex, false);

                }

            //}

          }

      //}

  //}

  //[선언정보판:보이기]
  //{
      //[!]{----------------------------------------------------------------------------
      //이 함수 자체가 <_AutoHide_WordBound()> 함수에서 호출되며 전달된 인수를 사용.
      //
      //공백 이동시에는 <_AutoHide_WordBound()> 함수 에서 [대상단어 시작위치 변경] 으로
      //간주되어 감춰진다.
      //즉, 공백은 연속적으로 처리되지 않는다.
      //}-------------------------------------------------------------------------------

      //[선택 단어가 있나?]
      //{
          //[2012.05.21.월][추가!!!]{-----------------------------------------
          //현재 [입력 지정자] 위치에 [단어] 가 없고 [공간] 상이라면
          //[입력 지정자] 가 위치한 [함수] 를 <infoTree> 가장 위치에 보여주고
          //[+] => [-] 로 열어서 정보를 보여준다.
          //즉, [현재 함수 알기] 기능으로 실제 꼭 필요한 기능이다.
          //
          //[단어:시작/끝 위치] 가 같다면 [공간] 상에 위치하는 것으로 본다.
          //
          //[주석]. [문자열], [문자상수] 안도 [무효공간] 으로 본다.
          //[실시간 선언 정보판] 안에 보여줄 정보가 없다.
          //}-----------------------------------------------------------------

          if((pWordIndexS == pWordIndexE) &&
             //[2012.06.24.일][추가!!!]
             //[구성원] 정보 요청이 아닌 경우만 해당.
             (DB_->_rtExpMark.opIndex == -1))
          {
            //[!]{------------------------------------------------------------------------
            //[재정렬] 시에는 이 경우는 존재할수 없다.
            //[공백] 으로 시작해도
            //1) 단어를 입력하는 경우는 [재정렬] 부분으로 인식하고.
            //2) 공백을 이동하는 경우는 [첫위치] 변화로 [실시간 선언 정보판] 이 감춰진다.
            //즉, 이 부분은 처리될수 없다.
            //
            //단, [단어] 가 있다가 계속 [Del/BackSpace] 로 [단어시작위치] 는 변경되지
            //않으면서 [공백] 이 되는 경우가 있다.
            //이 경우 예외처리 필요.
            //
            //[2012.06.24.일][중요추가!!!]************************************************
            //<InfoTree_Call()> 함수처럼 "->", "." 연산자 [구성원] 정보 보기를 지원.
            //반드시 <InfoTree_Call()> 함수는 한번 처리되고 이때 [구성원] 보기 정보는
            //다 추출돼 있으므로 여기서는 사용만 하면 된다.
            //
            //[구성원 정보 보기] 의 경우는 자동으로 아래의 <else> 에서 이미 수집된 정보로
            //[구성원 정보 보기] 상태가 계속 [유지] 된다.
            //}---------------------------------------------------------------------------

            rePainted = info_tree_Form->_TitleView_Func_DbRecIndex(DB_->_rtDefInfoEtc.funcRecIndex);

          }
          else
          {
            //[!]{-------------------------------------------------------
            //[단어] 가 있는 경우 [단어] 에 해당하는 정보를 가장 위에 보이기.
            //
            //[변수], [정의이름], [사용함수] 등 사용 정보가 해당.
            //[지역변수] 의 경우는 <DB_->_rtDefInfoEtc.funcRecIndex> 정보로
            //자동 구분된다.
            //}------------------------------------------------------------------

            //[인수] 로 전달받은 [시작/끝:위치] 사용하여 [전체단어] 를 추출.
            //[입력지정자] 위치까지의 [부분단어] 가 아니다!!!

            //[전체 단어 추출]
            //{
                STR_SubString(_editbuf,
                              pWordIndexS, pWordIndexE - pWordIndexS,
                              word);

            //}

            //[단어] 에 해당하는 항목 지정.
            rePainted = info_tree_Form->_TitleView_Word(DB_->_rtDefInfoEtc.funcRecIndex, word);

          }

      //}

      //[다시 그리기]
      //{
          //[2012.06.01.금][추가!!!]{--------------------------------------------
          //<_TitleView_Func_DbRecIndex()> 나 <_TitleView_Word()> 함수에서
          //[다시 그리기] 가 처리되지 않았다면 여기서 한번만 [다시 그리기] 한다.
          //
          //[2012.06.03.일][주석처리!!!]-----------------------------------------
          //보이기 전에 다시 그리도록위치를 <_ReShow()> 이전으로수정.
          //}--------------------------------------------------------------------

          if(rePainted != true)
          {
            //내용만 다시 그리므로 폼을 잘라내지 않는다.
            info_tree_Form->_TreeView(false, false);

          }

      //}

      //[표시]
      //{
          //[!]{---------------------------------------------------------------------
          //[선택항목/아래 귀뜸말] 보이기 기능만 처리.
          //[대상단어:시작/끝 위치] 는 이미 이 함수를 호출한 <_AutoHide_WordBound()>
          //에서 이미 저장하고 이 함수를 호출한 상태.
          //
          //금일 새로 만든 <_ReShow()> 함수안에서 모두 자동 처리된다.
          //}------------------------------------------------------------------------

          //[대상단어 지정(단어 아래 형광색 밑줄)] 까지 내부 처리.
          info_tree_Form->_ReShow();

          //[편집기] 에서 계속 편집가능하도록 다시 [편집기] 에 [촛점] 을 맞춘다.
          if(this->Focused() == false) { this->SetFocus(); }

      //}

      //[대상 단어 지정]
      //{
          //[!]{-------------------------------------------------------------------------
          //<info_tree_Form->_ReShow()> 함수 안에서 [실시간 선언 정보판] 을
          //보여주고 난 다음 바로 [단어 지정] 을 하므로 여기서는 처리하지 않는다.
          //이는 <info_tree_Form->_ReShow()> 안에 [귀뜸말] 처리부가 있어서 모두
          //처리하고 난 다음에 [단어지정] 을 하는 경우 약간의 [시간차] 가 발생하기 때문.
          //}----------------------------------------------------------------------------

      //}

  //}

}

/*
void __fastcall Teditor_edit_Form::InfoTree_ReCall(//입력지정자 위치 [전체단어] 시작위치.
                                                   int    pWordIndexS,
                                                   //입력지정자 위치 [전체단어] 끝위치.
                                                   int    pWordIndexE,
                                                   //[입력지정자] 위치까지의 부분단어.
                                                   char  *pPartWord_,
                                                   //<Ide_InfoTree_SetInfo()> 로 재정리 하는 경우는 <true>.
                                                   bool   pSetInfo)
{
  //[2012.06.01.금][생성!!!]{----------------------------------------------------
  //<_AutoHide_WordBound()> 함수에서 [근접단어정렬:재정리] 시에만 호출된다.
  //이를 위하여 <InfoTree_Call()> 함수를 바탕으로 특별하게 만든것.
  //
  //1) <Ctrl+Space> 로 <InfoTree_Call()> 함수가 한번 호출된 뒤에 사용해야 한다.
  //   이 함수는 [실시간 선언 정보판] 이 이미 보이고 있는 상태에서 [단어조합] 이
  //   연속되는 경우만 호출되기 때문.
  //
  //2) [재정리] 에 필요한 최소한의 처리만 수행(처리시간 단축을 위한것).
  //
  //[2012.06.03.일][수정!!!]-----------------------------------------------------
  //}----------------------------------------------------------------------------

  //[VAR]
  //{
      class DATABASE  *DB_;

      char  word[1024];

      //[2012.06.01.금][추가!!!]
      //처음에는 [다시 그리기] 된 것이 없는 것으로 초기화.
      bool  rePainted = false;

  //}

  //[DB 위치 얻기]{------
  DATABASE_GetPtr(&DB_);
  //}--------------------

  //[존재확인]
  //{
      //[선언정보판] 이 존재하지 않는다면 처리하지 않는다.
      if(info_tree_Form == NULL) return;

  //}


  //[선언정보판에 선언정보 정리]
  //{
      //[!]{----------------------------------------------
      //반드시 [근접단어정렬:재정리] 상태에서만 사용된다.
      //}-------------------------------------------------

      //[<근접단어정렬> 구분 처리]
      //{
          if(_ide_option->editorInfoTree_ClosedWord == true)
          {
            //[2012.05.30.수][추가!!!]{---------------------------------------------
            //[근접단어정렬] 인 경우는 현재 [입력 지정자 위치 단어] 전체가 아니라
            //이 단어에서 [입력지정자] 까지의 [단어] 만 추출하여 사용.
            //이는 [가장가까운단어] 를 계속 찾아서 [목록] 방식으로 보여주기 위한것.
            //}---------------------------------------------------------------------

            //<_AutoHide_WordBound()> 함수에서 [부분단어] 는 인수로 전달해 주지만
            //[전체단어] 는 구해서 전달하지 않고 [범위] 만 전달 하므로 [전체단어] 는 직접 구한다.

            //[근접단어정렬]
            //{
                //[참고!!!]{---------------------------------------------------
                //조건에 따라 [근접단어정렬] 방식으로 정리.
                //<word == ""> 인 경우는 내부에서 자동적으로 [근접단어정렬] 을
                ///사용하지 않고 [전체수집] 으로 처리된다.
                //}------------------------------------------------------------

                if(pSetInfo == true)
                {
                  //[!]{----------------------------------------------------------
                  //[재정리] 를 요청한 경우만 사용한다.
                  //<_AutoHide_WordBound()> 함수에서 [단어 미변경] 시에는
                  //[재정리] 할 필요는 없으나 [부가처리] 는 해야하는 경우도 있다.
                  //}-------------------------------------------------------------

                  Ide_InfoTree_SetInfo(pPartWord_, DB_->_rtDefInfoEtc.funcRecIndex, false);

                }

            //}

          }

      //}

  //}

  //[선언정보판:보이기]
  //{
      //[!]{----------------------------------------------------------------------------
      //이 함수 자체가 <_AutoHide_WordBound()> 함수에서 호출되며 전달된 인수를 사용.
      //
      //공백 이동시에는 <_AutoHide_WordBound()> 함수 에서 [대상단어 시작위치 변경] 으로
      //간주되어 감춰진다.
      //즉, 공백은 연속적으로 처리되지 않는다.
      //}-------------------------------------------------------------------------------

      //[선택 단어가 있나?]
      //{
          //[2012.05.21.월][추가!!!]{-----------------------------------------
          //현재 [입력 지정자] 위치에 [단어] 가 없고 [공간] 상이라면
          //[입력 지정자] 가 위치한 [함수] 를 <infoTree> 가장 위치에 보여주고
          //[+] => [-] 로 열어서 정보를 보여준다.
          //즉, [현재 함수 알기] 기능으로 실제 꼭 필요한 기능이다.
          //
          //[단어:시작/끝 위치] 가 같다면 [공간] 상에 위치하는 것으로 본다.
          //
          //[주석]. [문자열], [문자상수] 안도 [무효공간] 으로 본다.
          //[실시간 선언 정보판] 안에 보여줄 정보가 없다.
          //}-----------------------------------------------------------------

          if(pWordIndexS == pWordIndexE)
          {
            //[!]{------------------------------------------------------------------------
            //[재정렬] 시에는 이 경우는 존재할수 없다.
            //[공백] 으로 시작해도
            //1) 단어를 입력하는 경우는 [재정렬] 부분으로 인식하고.
            //2) 공백을 이동하는 경우는 [첫위치] 변화로 [실시간 선언 정보판] 이 감춰진다.
            //즉, 이 부분은 처리될수 없다.
            //
            //단, [단어] 가 있다가 계속 [Del/BackSpace] 로 [단어시작위치] 는 변경되지
            //않으면서 [공백] 이 되는 경우가 있다.
            //이 경우 예외처리 필요.
            //}---------------------------------------------------------------------------

            rePainted = info_tree_Form->_TitleView_Func_DbRecIndex(DB_->_rtDefInfoEtc.funcRecIndex);

          }
          else
          {
            //[!]{-------------------------------------------------------
            //[단어] 가 있는 경우 [단어] 에 해당하는 정보를 가장 위에 보이기.
            //
            //[변수], [정의이름], [사용함수] 등 사용 정보가 해당.
            //[지역변수] 의 경우는 <DB_->_rtDefInfoEtc.funcRecIndex> 정보로
            //자동 구분된다.
            //}------------------------------------------------------------------

            //[인수] 로 전달받은 [시작/끝:위치] 사용하여 [전체단어] 를 추출.
            //[입력지정자] 위치까지의 [부분단어] 가 아니다!!!

            //[전체 단어 추출]
            //{
                STR_SubString(_editbuf,
                              pWordIndexS, pWordIndexE - pWordIndexS,
                              word);

            //}

            //[단어] 에 해당하는 항목 지정.
            rePainted = info_tree_Form->_TitleView_Word(DB_->_rtDefInfoEtc.funcRecIndex, word);

          }

      //}

      //[다시 그리기]
      //{
          //[2012.06.01.금][추가!!!]{--------------------------------------------
          //<_TitleView_Func_DbRecIndex()> 나 <_TitleView_Word()> 함수에서
          //[다시 그리기] 가 처리되지 않았다면 여기서 한번만 [다시 그리기] 한다.
          //
          //[2012.06.03.일][주석처리!!!]-----------------------------------------
          //보이기 전에 다시 그리도록위치를 <_ReShow()> 이전으로수정.
          //}--------------------------------------------------------------------

          if(rePainted != true)
          {
            //내용만 다시 그리므로 폼을 잘라내지 않는다.
            info_tree_Form->_TreeView(false, false);

          }

      //}

      //[표시]
      //{
          //[!]{---------------------------------------------------------------------
          //[선택항목/아래 귀뜸말] 보이기 기능만 처리.
          //[대상단어:시작/끝 위치] 는 이미 이 함수를 호출한 <_AutoHide_WordBound()>
          //에서 이미 저장하고 이 함수를 호출한 상태.
          //
          //금일 새로 만든 <_ReShow()> 함수안에서 모두 자동 처리된다.
          //}------------------------------------------------------------------------

          //[대상단어 지정(단어 아래 형광색 밑줄)] 까지 내부 처리.
          info_tree_Form->_ReShow();

          //[편집기] 에서 계속 편집가능하도록 다시 [편집기] 에 [촛점] 을 맞춘다.
          if(this->Focused() == false) { this->SetFocus(); }

      //}

      //[대상 단어 지정]
      //{
          //[!]{-------------------------------------------------------------------------
          //<info_tree_Form->_ReShow()> 함수 안에서 [실시간 선언 정보판] 을
          //보여주고 난 다음 바로 [단어 지정] 을 하므로 여기서는 처리하지 않는다.
          //이는 <info_tree_Form->_ReShow()> 안에 [귀뜸말] 처리부가 있어서 모두
          //처리하고 난 다음에 [단어지정] 을 하는 경우 약간의 [시간차] 가 발생하기 때문.
          //}----------------------------------------------------------------------------

      //}

  //}

}

*/

void __fastcall Teditor_edit_Form::InfoTree_OnHide(void)
{
  //[2012.05.24.목][생성!!!]{----------------------------------------------------------
  //[실시간 선언 정보판] 의 [대상 단어] 로 지정된 부분을
  //해당 행만 다시 그려서 [해제] 시킨다.
  //단, 이 함수는 반드시 [실시간 선언 정보판] 이 [감추기] 된 후 사용해야 한다.
  //이는 <_EditBuf_LineText()> 함수에서 이 [보이기:유/무] 를 판별하여 처리하기 때문.
  //
  //[2012.05.25.금][수정!!!]-----------------------------------------------------------
  //현재 [편집기] 에서 관리되는 <_row> 정보로 [단어 지정] 을 해제하지 않고
  //[실시간 선언 정보판] 에서 관리한 <_edit_Row> 정보로 [해제] 한다.
  //
  //이는 [화면지정자] 로 [단어 구간] 을 벗어나 현재 [대상 단어] 가 해제되는 경우는
  //이미 <_row> 값이 새 위치의 것으로 변경된 것이라 이전 [대상 단어] 의 [단어 지정] 을
  //해제 하지 못하기 때문.
  //
  //[주의!!!]--------------------------------------------------------------------------
  //<info_tree_Form->_edit_Row> 값은 <info_tree_Form->_Show()> 호출부분에서 사전에
  //단 한번만 설정된다.
  //}----------------------------------------------------------------------------------

  //현재 행만 다시 그려 [해제].
  _EditBuf_LineText(info_tree_Form->_edit_Row, false);

}

void __fastcall Teditor_edit_Form::InfoTree_Cal_XY(//문서상 위치.
                                                   int   pIndex,
                                                   //계산한 좌표.
                                                   int  *rX,
                                                   int  *rY)
{
  //[2012.04.15.일][생성!!!]{---------------------------------------------------
  //문서상의 위치<index> 로 [실시간 선언정보판] 의 위치(X, Y) 를 계산하여 반환.
  //[실시간 선언정보판] 은 지정 위치가 있는 행의 [아래] 에 위치하게 된다.
  //
  //[참고!!!]-------------------------------------------------------------------
  //실제 [입력지정자] 위치와는 관계가 없으며 [문서 상의 위치] 와만 관계있다.
  //이상적으로 [실시간 선언정보판] 을 보여줄 위치를 계산하는데 목적이 있다.
  //
  //이 함수는 <History_SetCaretPos()> 함수를 참고하여 만들었다.
  //}---------------------------------------------------------------------------

  //[VAR]
  //{
      int  lineStartIndex;

      int  indexWidth;

      int  posX, posY;

      int  lineNumber;

  //}

  //[현재 위치 행번호 얻기]
  //{
      lineNumber = STR_Get_LineNumber_withIndex(_editbuf, pIndex);

  //}

  //[위치 행 시작 위치 얻기]
  //{
      //현재 지정 위치가 속한 행의 시작 위치 얻기.
      STR_Get_ThisLineStartIndex(_editbuf, pIndex, &lineStartIndex);

  //}

  //[위치 까지 폭 구하기]
  //{
      _CARETINDEX_CaretIndexWidth(lineStartIndex, pIndex, &indexWidth, NULL);

  //}

  //[좌표계산]
  //{
      //[주의!!!]{----------------------------------------------------------
      //눈에 보이는 영역안의 위치이므로 반드시 [문서원점] 을 반영해야 한다.
      //[줄이동] 된 경우 보이지 않는 영역에 존재할수도 있다.
      //}-------------------------------------------------------------------

      posX = _text_org_x + indexWidth;

      //[실시간 선언정보판] 은 항상 지정행 아래에 위치하므로 <+1> 한다.
      posY = _text_org_y + (lineNumber + 1) * _line_height;

  //}

  //[반환]
  //{
      if(rX != NULL) { (*rX) = posX; }
      if(rY != NULL) { (*rY) = posY; }

  //}

}

void __fastcall Teditor_edit_Form::InfoTree_AutoInput(void)
{
  //[2012.05.14.월][생성!!!]{--------------------------------------------------
  //현재 [입력지정자] 가 위치한 [단어] 를 <infoTree:항목> 으로 교체.
  //
  //1) <infoTree> 현재 항목의 <{DB}.name> 을 찾는다.
  //2) 현재 [편집기] 상 [입력지정자] 가 위치한 [단어] 를 [선택영역] 으로 지정.
  //3) <_EDIT_Paste()> 함수를 사용하여 <{DB}.name> 을 붙어넣기.
  //   이 과정은 [단어 교환] 기능과 유사.
  //
  //[주의!!!]------------------------------------------------------------------
  //이 함수는 반드시 <infoTree> 가 보이는 상태에서만 처리돼야 한다.
  //
  //[2012.06.02.토][중요수정!!!]-----------------------------------------------
  //[편집기] 의 현재 [입력지정자] 위치 단어를 교체시 [깜박임] 문제 수정.
  //}--------------------------------------------------------------------------

  //[VAR]
  //{
      class DATABASE   *DB_;

      struct INFOTREE  *infoTree;

      //<{DB}.name> 의 위치를 관리.
      char  *dbName = NULL;
      int    dbRecIndex;
      int    selIndex;

      int    nodeItemIndex;
      int    nodeLastItemIndex;

      int    wordStIndex;
      int    wordEdIndex;

  //}

  //[Database 의 주소를 얻기]
  //{
      DATABASE_GetPtr(&DB_);

  //}

  //[Tree 치환]
  //{
      //[문장] 을 간결하게 하기 위하여 [Tree] 를 [포인터] 로 받아서 사용한다.
      infoTree = &(info_tree_Form->_tree);

  //}

  //[<infoTree> 가 보이나?]
  //{
      //존재하지 않는다면 종료.
      if(info_tree_Form == NULL) return;

      //보이지 않는다면 종료.
      if(info_tree_Form->Visible != true) return;

  //}

  //[선택항목이 존재하나?]
  //{
      //[선택항목] 이 없다면 처리하지 않는다.
      if(infoTree->select_itemindex < 0) return;

      //[선택항목] 기록.
      selIndex = infoTree->select_itemindex;

  //}

  //[현재 [선택 항목] 의 <{DB}.name> 찾기]
  //{
      //[!]{------------------------------------------------------------
      //<tree->info1> 정보가 <{DB}:recindex> 에 해당.
      //<-1> 이 아니라면 해당 항목 정보가 {DB} 에 존재하는 것으로 본다.
      //
      //<Ide_TreeInfo_DoubleClick()> 함수를 참고.
      //}---------------------------------------------------------------

      //[{DB} 에 존재하나?]
      //{
          //[!]{-------------------------------------------
          //<{DB}:recindex> 정보가 없다면 처리하지 않는다.
          //}----------------------------------------------

          if(infoTree->items[infoTree->select_itemindex].info1 == -1) return;

      //}

      //[종류 구분 처리]
      //{
          //[!]{--------------------------------------------------------------------------------
          //<#define> 으로 선언된 것은 {definelist} 를 대상으로 해야 하므로 별도 구분하여 처리.
          //}-----------------------------------------------------------------------------------

          info_tree_Form->_Tree_Get_Node_LastItemIndex2(infoTree, "define", &nodeItemIndex, NULL, &nodeLastItemIndex);

          if((nodeItemIndex < selIndex) && (selIndex <= nodeLastItemIndex))
          {
            //[!]{------------------------------------------------------------
            //<#define> 으로 선언된 것이므로 {definelist[]} 를 대상으로 처리.
            //}---------------------------------------------------------------

            //[정보수집]
            //{
                dbRecIndex = infoTree->items[selIndex].info1;

                dbName     = DB_->definelist[dbRecIndex].defname;

            //}

          }
          else
          {
            //[!]{-----------------------------------
            //일반적인 경우로 {DB} 를 대상으로 처리.
            //}--------------------------------------

            //[정보수집]
            //{
                dbRecIndex = infoTree->items[selIndex].info1;

                dbName     = DB_->record[dbRecIndex].name;

            //}

          }

      //}

  //}

  //[함수 사용 제어]
  //{
      //[2012.06.02.토][추가!!!]{--------------------------------------------
      //<Tinfo_tree_Form::_AutoHide_WordBound()> 함수 처리 [금지] 제어.
      //
      //<History_SelectX()>, <_EDIT_Paste()> 함수를 처리시 내부에서 여러번
      //[중복] 될수 있고 처리되는 도중 [선택영역] 이 보이게 되어 [깜박임] 이
      //발생하는 문제를 제거하기 위한것.
      //}--------------------------------------------------------------------

      info_tree_Form->_sw_AutoHide_WordBound = false;

  //}

  //[입력지정자:스텔스 설정]
  //{
      //[2012.01.27.금][추가!!!]{---------------------------------------------
      //<_Find()> 함수에서 <History_SelectX()> 를 사용하고
      //<History_SelectX()> 함수안에서 <_EDIT_CaretPos()> 를 사용하는데
      //이 <_EDIT_CaretPos()> 에서 <gui_caret->_Position()> 함수를 사용하므로
      //처리시 [입력지정자] 가 자동으로 보이지 않도록 [스텔스] 로 설정한다.
      //
      //[편집기] 자체는 모든 처리를 완료후 한번만 그려주지만, [입력지정자] 는
      //계속 보여지므로 이를 방지하기 위한것.
      //}---------------------------------------------------------------------

      editor_edit_Form->_caret->_Stealth(true);

  //}

  //[<선택영역> 지정]
  //{
      //[!]{---------------------------------------------------
      //[입력지정자] 가 위치한 [단어] 를 [선택영역] 으로 지정.
      //}------------------------------------------------------

      //[입력 지정자] 가 위치한 [단어:시작/끝 위치] 얻기.
      STR_Get_WordBound(_editbuf, _filesize, _caretindex, &wordStIndex, &wordEdIndex);

      //[선택영역] 지정.
      History_SelectX(wordStIndex, wordEdIndex,
                      //[선택영역] 을 보이지 않는다(깜박임 방지).
                      false,
                      NULL,
                      //다시 그리지 않는다(깜박임 방지).
                      //아래 <_EDIT_Paste()> 에서 다시 그린다.
                      false,
                      false, false);

  //}

  //[<{DB}.name> 으로 대체]
  //{
      //[!]{-----------------------------------------
      //[선택영역] 의 [단어] 를 <{DB}.name> 로 교체.
      //}--------------------------------------------

      //다시 그리기 처리--v
      _EDIT_Paste(dbName, true);

  //}

  //[후처리]
  //{
      //문서가 수정됐음을 기록.
      _EDIT_Changed(false, true);

  //}

  //[입력지정자:스텔스 해제]
  //{
      //[2012.01.27.금][추가!!!]
      editor_edit_Form->_caret->_Stealth(false);

  //}

  //[함수 사용 제어]
  //{
      //[2012.06.02.토][추가!!!]{-------------------------------------
      //<Tinfo_tree_Form::_AutoHide_WordBound()> 함수 처리 허용 제어.
      //함수 사용을 [허가] 한다.
      //}-------------------------------------------------------------

      info_tree_Form->_sw_AutoHide_WordBound = true;

  //}

}

void __fastcall Teditor_edit_Form::InfoTree_Key_Enter(void)
{
  //[2012.05.14.월][생성!!!]{------------------
  //<infoTree> 의 <Key_Enter()> 를 호출.
  //단, <infoTree> 가 보이고 있는 경우만 처리.
  //}------------------------------------------

  //[보이나?]{--------------------------------
  //보이지 않는다면 처리하지 않는다.
  if(info_tree_Form->Visible != true) return;
  //}-----------------------------------------

  //[키제어]
  //{
      info_tree_Form->_Key_Enter();

  //}

}

void __fastcall Teditor_edit_Form::InfoTree_Key_Space(void)
{
  //[2012.05.14.월][생성!!!]{------------------
  //<infoTree> 의 <Key_Space()> 를 호출.
  //단, <infoTree> 가 보이고 있는 경우만 처리.
  //}------------------------------------------

  //[보이나?]{--------------------------------
  //보이지 않는다면 처리하지 않는다.
  if(info_tree_Form->Visible != true) return;
  //}-----------------------------------------

  //[키제어]
  //{
      info_tree_Form->_Key_Space();

  //}

}

void __fastcall Teditor_edit_Form::InfoTree_Key_Esc(void)
{
  //[2012.05.14.월][생성!!!]{------------------
  //<infoTree> 의 <Key_Esc()> 를 호출.
  //단, <infoTree> 가 보이고 있는 경우만 처리.
  //
  //[2012.06.28.목][수정!!!]-------------------
  //}------------------------------------------

  //[보이나?]{-------------------------------------------------------------
  //보이지 않는다면 처리하지 않는다.
  //
  //[2012.06.28.목][주석처리!!!]-------------------------------------------
  //이 부분은 아래 <info_tree_Form->_Key_Esc()> 함수 안에서 처리.
  //이는 [함수 선언 정보:귀뜸말] 인 경우는 독립적으로 동작할수 있기 때문에
  //[실시간 선언 정보판] 이 보이지 않는 상태에서도 [편집기:ESC] 로 닫을수
  //있어야 하기 때문.
  //if(info_tree_Form->Visible != true) return;
  //}----------------------------------------------------------------------

  //[키제어]
  //{
      info_tree_Form->_Key_Esc();

  //}

}

void __fastcall Teditor_edit_Form::InfoTree_Key_Up(void)
{
  //[2012.05.14.월][생성!!!]{------------------
  //<infoTree> 의 <Key_Up()> 을 호출.
  //단, <infoTree> 가 보이고 있는 경우만 처리.
  //
  //[2012.05.23.수][수정!!!]-------------------
  //}------------------------------------------

  //[보이나?]{--------------------------------
  //보이지 않는다면 처리하지 않는다.
  if(info_tree_Form->Visible != true) return;
  //}-----------------------------------------

  //[키제어]
  //{
      info_tree_Form->_Key_Up();

  //}

  //[촛점 설정]
  //{
      //[2012.05.23.수][추가!!!]{------------------------------------------
      //<info_tree_Form->_Key_Up()> 에서 [항목 선택] 시 아래에 [귀뜸말] 이
      //나오게 되는데 이때 [촛점] 은 <info_tree_Form> 에 맞추어 진다.
      //[편집기] 에서 동작시에는 항상 [편집기] 에 [촛점] 을 맞춘다.
      //}------------------------------------------------------------------

      if(this->Focused() == false) { this->SetFocus(); }

  //}

}

void __fastcall Teditor_edit_Form::InfoTree_Key_Down(void)
{
  //[2012.05.14.월][생성!!!]{------------------
  //<infoTree> 의 <Key_Down()> 을 호출.
  //단, <infoTree> 가 보이고 있는 경우만 처리.
  //
  //[2012.05.23.수][수정!!!]-------------------
  //}------------------------------------------

  //[보이나?]{--------------------------------
  //보이지 않는다면 처리하지 않는다.
  if(info_tree_Form->Visible != true) return;
  //}-----------------------------------------

  //[키제어]
  //{
      info_tree_Form->_Key_Down();

  //}

  //[촛점 설정]
  //{
      //[2012.05.23.수][추가!!!]{------------------------------------------
      //<info_tree_Form->_Key_Up()> 에서 [항목 선택] 시 아래에 [귀뜸말] 이
      //나오게 되는데 이때 [촛점] 은 <info_tree_Form> 에 맞추어 진다.
      //[편집기] 에서 동작시에는 항상 [편집기] 에 [촛점] 을 맞춘다.
      //}------------------------------------------------------------------

      if(this->Focused() == false) { this->SetFocus(); }

  //}

}

//******************************************************************************
//[<Ctrl+P> 관련]***************************************************************
//******************************************************************************

void __fastcall Teditor_edit_Form::ApiTree_Ctrl_P(void)
{
  //[2022.07.05.화][생성]{---------------------------------------------------------------
  //<Ctrl+P> 가 눌린 경우 처리를 수행.
  //
  //현재 [입력지정자] 가 위치한 [단어] 를 <Tree:API 검색> 에서 검색하고 결과를 보여준다.
  //}------------------------------------------------------------------------------------

  //[방법]{****************************************************************************
  //
  //1) [입력지정자] 가 위치한 [단어] 추출(입력지정자 위치까지).
  //
  //2) <Tree:API> 로 전환하고 <Tree:API 검색> 을 활성화.
  //
  //3) <Tree:API 검색> 의 [한줄편집기] 에 1) 의 추출 단어를 출력.
  //
  //4) <ide_tree_Form->_EVENT_findEdit_Change()> 가 동작하면서 단어 검색 후 결과 출력.
  //
  //현재는 [실시간 선언정보판] 과 같이 처리하지 않고, <Ctrl+P> 를 누를때마다 찾아주는
  //참고용 기능으로 처리한다.
  //}**********************************************************************************

  //[VAR]
  //{
      char  word_[1024];

      int   wordStartIndex, wordEndIndex;

  //}

  //[현재 입력 지정자 위치 단어 얻기]
  //{
      //[<입력지정자> 까지 단어 정보 얻기]
      //{
          STR_Get_WordBound(_editbuf, _filesize, _caretindex,
                            &wordStartIndex,
                            &wordEndIndex);

      //}                      

      //[<입력지정자> 위치까지의 단어 추출]
      //{
          if(wordStartIndex == wordEndIndex)
          {
            //추출할 단어가 없으므로 더이상 처리하지 않는다.
            return;

          }
          else
          {
            //단어 추출(일단 전체 단어 추출).
            STR_SubString(_editbuf,
                          //[부분단어사용]{-------------------------------
                          //[입력지정자] 위치까지만 단어를 추출하는 경우.
                          //wordStartIndex, _caretindex - wordStartIndex,
                          //[전체단어사용]--------------------------------
                          //[입력지정자] 가 위치한 단어 전체 얻는 경우.
                          wordStartIndex, wordEndIndex - wordStartIndex,
                          //}---------------------------------------------
                          word_);

          }                

      //}

  //}

  //[<Tree:API> 로 전환 및 <API 검색> 활성화]
  //{
      //<Tree:API> 로 전환.
      ide_tree_Form->_tabs_Form->_TabIndex(d_TREE_api);

      //<API 검색> 활성화.
      tree_tree_Form->_Key_Ctrl_F();

      //[편집기] 에서 <Ctrl+P> 로 활성화 된 것임을 알린다.
      ide_tree_Form->_editor_Ctrl_P = true;

  //}

  //[검색 단어 출력]
  //{
      ide_tree_Form->_findEdit->_EDIT_TextOut(word_);

      //[입력지정자] 를 문자열 끝에 위치 시킨다.
      //항상 [입력지정자] 가 보이는 위치에 있도록 처리.
      //---------------------------------v
      ide_tree_Form->_findEdit->_KEY_End(true);

  //}

  //[검색]
  //{
      ide_tree_Form->_EVENT_findEdit_Change();

  //}

}







