 
//--------------------------------------------------------------------- 
#include "cmtw_utils.h" 
#include <windowsx.h> 
#include "resource.h" 
//--------------------------------------------------------------------- 
 
//--------------------------------------------------------------------- 
WWindow::WWindow () 
{ 
  _window = NULL; 
} 
 
void WWindow::enable () 
{ 
  EnableWindow (_window, TRUE); 
} 
 
void WWindow::disable () 
{ 
  EnableWindow (_window, FALSE); 
} 
 
void WWindow::show () 
{ 
  ShowWindow (_window, SW_SHOW); 
} 
 
void WWindow::hide () 
{ 
  ShowWindow (_window, SW_HIDE); 
} 
//--------------------------------------------------------------------- 
 
//--------------------------------------------------------------------- 
WEdit::WEdit () 
{ 
  _edit = NULL; 
} 
 
WEdit::WEdit (HWND edit) 
{ 
  _edit = edit; 
  _window = _edit; 
} 
 
WEdit::WEdit (HWND container, int id) 
{ 
  _edit = GetDlgItem (container, id); 
  _window = _edit; 
} 
 
void WEdit::init (HWND container, int id) 
{ 
  _edit = GetDlgItem (container, id); 
  _window = _edit; 
} 
 
WEdit& WEdit::operator = (HWND edit) 
{ 
  _edit = edit; 
  _window = _edit; 
  return (*this); 
} 
 
void WEdit::set (const char* text) 
{ 
  int status = SendMessage (_edit, WM_SETTEXT, (WPARAM) 0, (LPARAM) text); 
} 
 
void WEdit::set (const cmt_string& text) 
{ 
  set (text.c_str ()); 
} 
 
void WEdit::clear () 
{ 
  set (""); 
} 
 
cmt_string WEdit::get () const 
{ 
  int size = SendMessage (_edit, WM_GETTEXTLENGTH, (WPARAM) 0, (LPARAM) 0); 
 
  cmt_string text (size); 
 
  SendMessage (_edit, WM_GETTEXT, (WPARAM) size + 1, (LPARAM) text.c_str ()); 
 
  return (text); 
} 
 
void WEdit::copy (const WEdit& other) 
{ 
  clear (); 
  set (other.get ()); 
} 
//--------------------------------------------------------------------- 
 
//--------------------------------------------------------------------- 
WRadio::WRadio () 
{ 
  _radio = NULL; 
} 
 
WRadio::WRadio (HWND radio) 
{ 
  _radio  = radio; 
  _window = _radio; 
} 
 
WRadio::WRadio (HWND container, int id) 
{ 
  _radio = GetDlgItem (container, id); 
  _window = _radio; 
} 
 
void WRadio::init (HWND container, int id) 
{ 
  _radio = GetDlgItem (container, id); 
  _window = _radio; 
} 
 
WRadio& WRadio::operator = (HWND radio) 
{ 
  _radio  = radio; 
  _window = _radio; 
  return (*this); 
} 
 
void WRadio::set (bool state) 
{ 
  int status = SendMessage (_radio, BM_SETCHECK,  
	  (WPARAM) (state) ? BST_CHECKED : BST_UNCHECKED, 
	  (LPARAM) 0); 
} 
 
bool WRadio::get () const 
{ 
  bool result = (SendMessage (_radio,  
	  BM_GETCHECK, (WPARAM) 0, (LPARAM) 0) == BST_CHECKED); 
 
  return (result); 
} 
 
void WRadio::copy (const WRadio& other) 
{ 
  set (other.get ()); 
} 
//--------------------------------------------------------------------- 
 
//--------------------------------------------------------------------- 
WList::WList () 
{ 
  _list = NULL; 
  _selected_index = -1; 
  _width = 0; 
} 
 
WList::WList (HWND list) 
{ 
  _list = list; 
  _window = _list; 
  _width = get_width (); 
  set_extent (); 
  get_selected_index (); 
} 
 
WList::WList (HWND container, int id) 
{ 
  _list = GetDlgItem (container, id); 
  _window = _list; 
  _width = get_width (); 
  set_extent (); 
  get_selected_index (); 
} 
 
void WList::init (HWND container, int id) 
{ 
  _list = GetDlgItem (container, id); 
  _window = _list; 
  _width = get_width (); 
  set_extent (); 
  get_selected_index (); 
} 
 
WList& WList::operator = (HWND list) 
{ 
  _list = list; 
  _window = _list; 
  _width = get_width (); 
  set_extent (); 
  get_selected_index (); 
  return (*this); 
} 
 
void WList::append (const char* text) 
{ 
  SendMessage (_list, LB_INSERTSTRING, (WPARAM) -1, (LPARAM) text); 
  int w = strlen (text); 
  if (w > _width)  
  { 
    _width = w; 
    set_extent (); 
  } 
} 
 
void WList::append (const cmt_string& text) 
{ 
  SendMessage (_list, LB_INSERTSTRING, (WPARAM) -1, (LPARAM) text.c_str ()); 
  int w = text.size (); 
  if (w > _width)  
  { 
    _width = w; 
    set_extent (); 
  } 
} 
 
void WList::insert (int index, const cmt_string& text) 
{ 
  SendMessage (_list, LB_INSERTSTRING, (WPARAM) index, (LPARAM) text.c_str ()); 
  int w = text.size (); 
  if (w > _width)  
  { 
    _width = w; 
    set_extent (); 
  } 
} 
 
void WList::modify (int index, const cmt_string& text) 
{ 
  SendMessage (_list, LB_DELETESTRING, (WPARAM) index, (LPARAM) 0); 
  SendMessage (_list, LB_INSERTSTRING, (WPARAM) index, (LPARAM) text.c_str ()); 
 
  _width = get_width (); 
  set_extent (); 
} 
 
void WList::delete_item (int index) 
{ 
  SendMessage (_list, LB_DELETESTRING, (WPARAM) index, (LPARAM) 0); 
 
  _width = get_width (); 
  set_extent (); 
} 
 
void WList::clear () 
{ 
  SendMessage (_list, LB_RESETCONTENT, (WPARAM) 0, (LPARAM) 0); 
  _selected_index = -1; 
  _width = 0; 
  set_extent (); 
} 
 
void WList::cancel_selection () 
{ 
  SendMessage (_list, LB_SETCURSEL, (WPARAM) -1, (LPARAM) 0); 
  _selected_index = -1; 
} 
 
int WList::get_selected_index () 
{ 
  int index; 
                 
  index = SendMessage (_list, LB_GETCURSEL, (WPARAM) 0, (LPARAM) 0); 
  _selected_index = index; 
 
  return (index); 
} 
 
void WList::set_selected_index (int index) 
{ 
  SendMessage (_list, LB_SETCURSEL, (WPARAM) index, (LPARAM) 0); 
  _selected_index = index; 
} 
 
cmt_string WList::get_selected () 
{ 
  int index = get_selected_index (); 
 
  int size = SendMessage (_list, LB_GETTEXTLEN, (WPARAM) index, (LPARAM) 0); 
 
  cmt_string text (size + 1); 
 
  SendMessage (_list, LB_GETTEXT, (WPARAM) index, (LPARAM) text.c_str ()); 
 
  return (text); 
} 
 
int WList::get_item_count () const 
{ 
  int item; 
         
  item = SendMessage (_list, LB_GETCOUNT, (WPARAM) 0, (LPARAM) 0); 
 
  return (item); 
} 
 
cmt_string WList::get_item (int index) const 
{ 
  int size = SendMessage (_list, LB_GETTEXTLEN, (WPARAM) index, (LPARAM) 0); 
 
  cmt_string text (size + 1); 
         
  SendMessage (_list, LB_GETTEXT, (WPARAM) index, (LPARAM) text.c_str ()); 
 
  return (text); 
} 
 
void WList::get_item (int index, cmt_string& text) const 
{ 
  int size = SendMessage (_list, LB_GETTEXTLEN, (WPARAM) index, (LPARAM) 0); 
 
  static cmt_string temp; 
  temp.resize (size); 
	   
  SendMessage (_list, LB_GETTEXT, (WPARAM) index, (LPARAM) temp.c_str ()); 
 
  text = temp; 
} 
 
int WList::get_item_length (int index) const 
{ 
  int size = SendMessage (_list, LB_GETTEXTLEN, (WPARAM) index, (LPARAM) 0); 
 
  return (size); 
} 
 
void WList::copy (const WList& other) 
{ 
  int items; 
  int i; 
 
  clear (); 
 
  items = other.get_item_count (); 
  for (i = 0; i < items; i++) 
    { 
      append (other.get_item (i)); 
    } 
} 
 
void WList::set (const CmtSystem::cmt_string_vector& v, int first) 
{ 
  int i; 
 
  clear (); 
 
  for (i = first; i < v.size (); i++) 
    { 
      append (v[i]); 
    } 
} 
 
void WList::set (const cmt_string& file_name) 
{ 
  clear (); 
 
  cmt_string text; 
  cmt_string line; 
  int pos; 
  int max_pos; 
 
  text.read (file_name); 
 
  pos = 0; 
  max_pos = text.size (); 
 
  for (pos = 0; pos < max_pos;) 
    { 
      int cr = text.find (pos, "\r\n"); 
      int nl = text.find (pos, '\n');  
      int first = nl; 
      int length = 1; 
 
      if (cr != cmt_string::npos) 
        { 
          if (nl == cmt_string::npos) 
            { 
              first = cr; 
              length = 2; 
            } 
          else 
            { 
              first = (nl < cr) ? nl : cr; 
              length = (nl < cr) ? 1 : 2; 
            } 
        } 
 
      if (first == cmt_string::npos) 
        { 
          text.substr (pos, line); 
          pos = max_pos; 
        } 
      else if (first > pos) 
        { 
          text.substr (pos, first - pos, line); 
          pos = first + length; 
        } 
      else 
        { 
          line = ""; 
          pos += length; 
        } 
 
      append (line); 
    } 
} 
 
void WList::get (CmtSystem::cmt_string_vector& v) const 
{ 
  int count = get_item_count (); 
  int i; 
 
  v.clear (); 
 
  for (i = 0; i < count; i++) 
    { 
      v.push_back (get_item (i)); 
    } 
} 
 
void WList::get (cmt_string& s) const 
{ 
  int count = get_item_count (); 
  int i; 
 
  s = ""; 
 
  for (i = 0; i < count; i++) 
    { 
      if (i > 0) s += '\n'; 
      s += get_item (i); 
    } 
} 
 
void WList::set_extent () 
{ 
  int width = get_extent (); 
  ListBox_SetHorizontalExtent (_list, width); 
} 
 
int WList::get_width () const 
{ 
  if (_list == 0) return (0); 
 
  int count = get_item_count (); 
  int w = 0; 
 
  int i; 
  for (i = 0; i < count; i++) 
  { 
	  int length = get_item_length (i); 
	  if (length > w) w = length; 
  } 
 
  return (w); 
} 
 
int WList::get_extent () const 
{ 
  if (_width == 0) return (0); 
 
  cmt_string text (_width + 1); 
 
  HDC context = GetDC (_list); 
  int saved_context = SaveDC (context); 
  HFONT font = GetWindowFont (_list); 
  if (font != NULL) SelectFont (context, font); 
 
  int w = 0; 
 
  int count = get_item_count (); 
 
  int i; 
  for (i = 0; i < count; i++) 
  { 
	  SIZE size; 
 
	  get_item (i, text); 
	  GetTextExtentPoint32 (context, text.c_str (), text.size (), &size); 
	  if (size.cx > w) w = size.cx; 
  } 
 
  RestoreDC (context, saved_context); 
  ReleaseDC (_list, context); 
 
  w += GetSystemMetrics (SM_CXVSCROLL); 
 
  return (w); 
} 
//--------------------------------------------------------------------- 
 
//--------------------------------------------------------------------- 
void WTab::add (const cmt_string& key, WWindow& window, WRadio& radio) 
{ 
	_keys.push_back (key); 
	_windows.push_back (&window); 
	_radios.push_back (&radio); 
} 
 
void WTab::select (const cmt_string& key) 
{ 
	int i; 
	for (i = 0; i < _keys.size (); i++) 
	{ 
		const cmt_string& k = _keys[i]; 
		if (k == key) 
		{ 
			for (int j = 0; j < _keys.size (); j++) 
			{ 
				WWindow* w = _windows[j]; 
				WRadio* r = _radios[j]; 
				if (i == j)  
				{ 
					w->show (); 
					r->set (true); 
				} 
				else 
				{ 
					w->hide (); 
					r->set (false); 
				} 
			} 
			return; 
		} 
	} 
} 
 
//--------------------------------------------------------------------- 
 
//--------------------------------------------------------------------- 
mysb::mysb (WList& list) : _list (list) 
{ 
    //list_clear (list); 
  _buf = 0; 
#ifdef OLD_HEADERS 
  _old = cout.rdbuf (); 
  cout = this; 
#else 
  _old = cout.rdbuf (this); 
#endif 
} 
 
mysb::~mysb () 
{ 
  if (_buf != 0) 
  { 
    delete _buf; 
	_buf = 0; 
  } 
 
#ifdef OLD_HEADERS 
  cout = _old; 
#else 
  cout.rdbuf (_old); 
#endif 
} 
 
int_type mysb::overflow (int_type c) 
{ 
  if (_buf == 0) 
  { 
    _buf = new cmt_string; 
  } 
 
  cmt_string& buf = *_buf; 
 
  if (c == '\n') 
    { 
      _list.append (buf); 
      buf = ""; 
    } 
  else 
    { 
      buf += c; 
    } 
  return (c); 
} 
         
int mysb::underflow () 
{ 
  return (EOF); 
} 
//--------------------------------------------------------------------- 
 
//--------------------------------------------------------------------- 
WDialog::WDialog () 
{ 
} 
 
void WDialog::action (UINT message_type, 
                      WPARAM parameter1, 
                      LPARAM parameter2) 
{ 
} 
 
void WDialog::init_action () 
{ 
} 
 
void WDialog::menu_action (int menu_item, 
                           WPARAM parameter1, 
                           LPARAM parameter2) 
{ 
  switch (menu_item)  
    { 
      case IDOK: 
        break; 
      case IDCANCEL: 
        break; 
      default: 
        break; 
    } 
} 
 
int WDialog::run (HINSTANCE instance, HWND father, int id) 
{ 
  return (DialogBoxParam (instance,  
                          MAKEINTRESOURCE(id),  
                          father, 
                          (DLGPROC) proc, 
                          (LPARAM) this)); 
} 
 
LRESULT CALLBACK WDialog::proc (HWND dialog, 
                                UINT message_type, 
                                WPARAM parameter1, 
                                LPARAM parameter2) 
{ 
  static cmt_vector <WDialog*> objects; 
  WDialog* object = NULL; 
  int menu_item; 
 
  switch (message_type)  
    { 
      case WM_CREATE: 
        break; 
      case WM_SETFONT: 
        break; 
      case WM_INITDIALOG: 
        object = (WDialog*) parameter2; 
        if (object != NULL) 
          { 
            objects.push_back (object); 
 
            object->_dialog = dialog; 
            object->init_action (); 
          } 
        break; 
      case WM_COMMAND: 
        menu_item = LOWORD (parameter1); 
 
        if (objects.size () > 0) 
          { 
            object = objects.back (); 
          } 
 
        if (object != NULL) 
          { 
            object->menu_action (menu_item, parameter1, parameter2); 
          } 
 
        switch (menu_item)  
          { 
            case IDOK: 
              EndDialog (dialog, IDOK); 
              objects.pop_back (); 
              break; 
            case IDCANCEL: 
              EndDialog (dialog, IDCANCEL); 
              objects.pop_back (); 
              break; 
            default: 
              break; 
          } 
        break; 
      default: 
        if (objects.size () > 0) 
          { 
            object = objects.back (); 
          } 
 
        if (object != NULL) 
          { 
            object->action (message_type, parameter1, parameter2); 
          } 
        return (FALSE); 
    } 
  return (TRUE); 
} 
//--------------------------------------------------------------------- 
 
//--------------------------------------------------------------------- 
TextEditor::TextEditor (cmt_string& ref) : _ref (ref) 
{ 
} 
 
int TextEditor::run (HINSTANCE instance, HWND father) 
{ 
  return (WDialog::run (instance, father, IDD_TEXTEDIT)); 
} 
 
void TextEditor::action (UINT message_type, 
                         WPARAM parameter1, 
                         LPARAM parameter2) 
{ 
} 
 
void TextEditor::init_action () 
{ 
  _edit = GetDlgItem (_dialog, IDTE_TEXT); 
  _edit.set (_ref); 
} 
 
void TextEditor::menu_action (int menu_item, WPARAM parameter1, LPARAM parameter2) 
{ 
  switch (menu_item)  
    { 
      case IDOK: 
        _ref = _edit.get (); 
        break; 
      case IDCANCEL: 
        break; 
      default: 
        break; 
    } 
} 
//--------------------------------------------------------------------- 
 
//--------------------------------------------------------------------- 
ListEditor::ListEditor (WList& list) : _ref_list (list) 
{ 
} 
 
int ListEditor::run (HINSTANCE instance, HWND father) 
{ 
  _instance = instance; 
  return (WDialog::run (instance, father, IDD_LISTEDIT)); 
} 
 
void ListEditor::action (UINT message_type, 
                         WPARAM parameter1, 
                         LPARAM parameter2) 
{ 
} 
 
void ListEditor::set_position (int index) 
{ 
  _list.set_selected_index (index); 
  _selected_index = index; 
  _last_index = index; 
} 
 
void ListEditor::init_action () 
{ 
  _list.init (_dialog, IDLE_LIST); 
  _list.copy (_ref_list); 
  _ref_selected_index = _ref_list.get_selected_index (); 
  _list.set_selected_index (_ref_selected_index); 
  _selected_index = _ref_selected_index; 
  _last_index = _ref_selected_index; 
} 
 
void ListEditor::menu_action (int menu_item, WPARAM parameter1, LPARAM parameter2) 
{ 
  int index = _list.get_selected_index (); 
 
  switch (menu_item)  
    { 
      case IDOK: 
        _ref_list.copy (_list); 
        _ref_list.set_selected_index (_ref_selected_index); 
        break; 
      case IDCANCEL: 
        break; 
      case IDLE_ADD: 
      { 
        cmt_string s; 
        TextEditor editor (s); 
 
        if (editor.run (_instance, _dialog) == IDOK) 
          { 
            _list.insert (index, s); 
          } 
      } 
      break; 
      case IDLE_REMOVE: 
      { 
        if (index != -1) 
          { 
            _list.delete_item (index); 
          } 
      } 
      break; 
      case IDLE_LIST: 
     { 
        switch (HIWORD(parameter1)) 
          { 
            case LBN_DBLCLK: 
            { 
              if (index == -1) index = _last_index; 
              cmt_string s = _list.get_item (index); 
              TextEditor editor (s); 
         
              if (editor.run (_instance, _dialog) == IDOK) 
                { 
                  _list.modify (index, s); 
                } 
              _list.set_selected_index (index); 
              _selected_index = index; 
              _last_index = index; 
            } 
            break; 
            case LBN_SELCHANGE: 
              if (_selected_index == -1) 
                { 
                  _selected_index = index; 
                  _last_index = index; 
                } 
              else if (_selected_index == index) 
                { 
                  _list.cancel_selection (); 
                  _selected_index = -1; 
                } 
              else 
                { 
                  _selected_index = index; 
                  _last_index = index; 
                } 
              break; 
            case LBN_SELCANCEL: 
            { 
            } 
            break; 
          } 
      } 
      break; 
      default: 
        break; 
    } 
} 
//--------------------------------------------------------------------- 
 
//--------------------------------------------------------------------- 
CmtMutex::CmtMutex () 
{ 
  InitializeCriticalSection (&_section); 
} 
 
CmtMutex::~CmtMutex () 
{ 
  DeleteCriticalSection (&_section); 
} 
 
void CmtMutex::lock () 
{ 
  EnterCriticalSection (&_section); 
} 
 
void CmtMutex::unlock () 
{ 
  LeaveCriticalSection (&_section); 
} 
//--------------------------------------------------------------------- 
 
//--------------------------------------------------------------------- 
CmtThread::CmtThread () 
{ 
  _shutdown = FALSE; 
  _running = FALSE; 
} 
 
CmtThread::~CmtThread () 
{ 
} 
 
void CmtThread::run () 
{ 
} 
 
bool CmtThread::is_running () 
{ 
  bool result = false; 
 
  _mutex.lock (); 
  result = _running; 
  _mutex.unlock (); 
 
  return (result); 
} 
 
void CmtThread::set_running () 
{ 
  _mutex.lock (); 
  _running = TRUE; 
  _mutex.unlock (); 
} 
 
void CmtThread::reset_running () 
{ 
  _mutex.lock (); 
  _running = FALSE; 
  _mutex.unlock (); 
} 
 
bool CmtThread::start () 
{ 
  if (!is_running ()) 
    { 
      _thread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) run_it, 
                              this, 0, &_id); 
 
	  return (TRUE); 
    } 
  else 
    { 
	  return (FALSE); 
    } 
} 
 
void CmtThread::stop () 
{ 
  _mutex.lock (); 
  _shutdown = TRUE; 
  _mutex.unlock (); 
 
  WaitForSingleObject (_thread, INFINITE); 
} 
 
void CmtThread::run_it (CmtThread* thread) 
{ 
  thread->set_running (); 
  thread->run (); 
  thread->reset_running (); 
} 
//--------------------------------------------------------------------- 
 
