Exemple #1
0
LRESULT CProgressDlg::OnCopyLog(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
  CString sData;
  int i;
  for(i=0; i<m_listView.GetItemCount(); i++)
  {
    TCHAR buf[4096];
    buf[0]=0;
    int n = m_listView.GetItemText(i, 0, buf, 4095);
    sData += CString(buf,n);
    sData += "\r\n";
  }

  SetClipboard(sData);  

  return 0;
}
Exemple #2
0
void Command::Execute () {
    Selection* s = _editor->GetSelection();
    Clipboard* cb = GetClipboard();

    if (!s->IsEmpty() || (cb != nil && !cb->IsEmpty())) {
        Iterator i;

        if (cb == nil) {
            SetClipboard(cb = new Clipboard);
            cb->Init(s);
        }

        for (cb->First(i); !cb->Done(i); cb->Next(i)) {
            cb->GetComp(i)->Interpret(this);
        }
        unidraw->Update();
    }
}
LRESULT CRepositoryFilterView::OnBnClickedButtonCopy(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
    if (m_Root)
    {
        std::_tstring attrs;
        WTL::CTreeItem item = *m_Root;
        while(item)
        {
            if (CComQIPtr<CAttributeNode> node = reinterpret_cast<CTreeNode *>(item.GetData()))
            {
                if (!attrs.empty())
                    attrs += _T("\r\n");
                attrs += node->GetAttribute()->GetQualifiedLabel();
            }
            item = m_Tree.GetNextItem(item, TVGN_EX_ALL);
        }
        SetClipboard(attrs);
    }
    return 0;
}
Exemple #4
0
LRESULT CProgressDlg::OnCopySel(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
  CString sData;
  int i;
  for(i=0; i<m_listView.GetItemCount(); i++)
  {
    DWORD dwState = m_listView.GetItemState(i, LVIS_SELECTED);
    if(dwState==0)
      continue;

    TCHAR buf[4096];
    buf[0]=0;
    int n = m_listView.GetItemText(i, 0, buf, 4095);
    sData += CString(buf,n);
    sData += "\r\n";
  }

  SetClipboard(sData);  

  return 0;
}
Exemple #5
0
void AlignToGridCmd::Execute () {
    Selection* s = _editor->GetSelection();

    if (!s->IsEmpty()) {
        Clipboard* cb = GetClipboard();
        Iterator i;

        if (cb == nil) {
            for (s->First(i); !s->Done(i); s->Next(i)) {
                s->GetView(i)->Interpret(this);
            }

            SetClipboard(cb = new Clipboard);
            cb->Init(s);

        } else {
            for (cb->First(i); !cb->Done(i); cb->Next(i)) {
                Move(cb->GetComp(i));
            }
        }
        unidraw->Update();
    }
}
Exemple #6
0
void CMainFrame::OnCopyCrossreference()
{
    std::_tstring xref;
    SetClipboard(m_dependees.GetCrossreferenced(xref));
}
uint32 FolderWindow::onMessage(uint32 message, uint32 wParam, uint32 lParam)
{
    switch (message)
    {
    case WM_CONTEXTMENU:
    {
        POINT pt;
        GetCursorPos(&pt);

        int count = ListView_GetSelectedCount(list->getHandle());
        int item = ListView_GetNextItem(list->getHandle(), -1, LVNI_SELECTED);
        if (item >= 0)
        {
            int pos = list->getItemParam(item);
            while (count > 1 && item >= 0 && items[pos].type != ITEM_FOLDER &&
                    items[pos].type != ITEM_REPLAY)
            {
                item = ListView_GetNextItem(list->getHandle(), item, LVNI_SELECTED);
                pos = (item > 0 ? list->getItemParam(item) : -1);
            }

            EnableMenuItem(ctxMenu, ID_MENU_OPEN, count > 1 ? MF_GRAYED : MF_ENABLED);
            if (pos >= 0 && (items[pos].type == ITEM_FOLDER || items[pos].type == ITEM_REPLAY))
            {
                EnableMenuItem(ctxMenu, ID_MENU_BACKUP, MF_ENABLED);
                EnableMenuItem(ctxMenu, ID_MENU_COPY, MF_ENABLED);
                EnableMenuItem(ctxMenu, ID_MENU_DELETE, MF_ENABLED);
                EnableMenuItem(ctxMenu, ID_MENU_RENAME, count > 1 ? MF_GRAYED : MF_ENABLED);
            }
            else
            {
                EnableMenuItem(ctxMenu, ID_MENU_BACKUP, MF_GRAYED);
                EnableMenuItem(ctxMenu, ID_MENU_COPY, MF_GRAYED);
                EnableMenuItem(ctxMenu, ID_MENU_DELETE, MF_GRAYED);
                EnableMenuItem(ctxMenu, ID_MENU_RENAME, MF_GRAYED);
            }
        }
        else
        {
            EnableMenuItem(ctxMenu, ID_MENU_OPEN, MF_GRAYED);
            EnableMenuItem(ctxMenu, ID_MENU_BACKUP, MF_GRAYED);
            EnableMenuItem(ctxMenu, ID_MENU_COPY, MF_GRAYED);
            EnableMenuItem(ctxMenu, ID_MENU_DELETE, MF_GRAYED);
            EnableMenuItem(ctxMenu, ID_MENU_RENAME, MF_GRAYED);
        }
        ClipboardReader cbReader(CF_HDROP);
        EnableMenuItem(ctxMenu, ID_MENU_PASTE, cbReader.getData() ? MF_ENABLED : MF_GRAYED);

        int result = TrackPopupMenuEx(ctxMenu, TPM_HORIZONTAL | TPM_LEFTALIGN |
                                      TPM_RETURNCMD | TPM_NONOTIFY, pt.x, pt.y, list->getHandle(), NULL);

        switch (result)
        {
        case ID_MENU_OPEN:
        {
            NMITEMACTIVATE ia;
            memset(&ia, 0, sizeof ia);
            ia.hdr.code = LVN_ITEMACTIVATE;
            ia.hdr.hwndFrom = list->getHandle();
            ia.iItem = item;
            onMessage(WM_NOTIFY, 0, (uint32) &ia);
        }
        break;
        case ID_MENU_BACKUP:
        {
            BatchDialog batch(BatchDialog::mCopy);
            for (int item = ListView_GetNextItem(list->getHandle(), -1, LVNI_SELECTED);
                    item >= 0; item = ListView_GetNextItem(list->getHandle(), item, LVNI_SELECTED))
            {
                int pos = list->getItemParam(item);
                if (pos >= 0 && items[pos].type == ITEM_REPLAY)
                    batch.addReplay(items[pos].path);
                else if (pos >= 0 && items[pos].type == ITEM_FOLDER)
                    batch.addFolder(items[pos].path);
            }
            batch.run(list->getHandle());
        }
        break;
        case ID_MENU_COPY:
        case ID_MENU_PASTE:
        case ID_MENU_DELETE:
        case ID_MENU_RENAME:
        {
            NMLVKEYDOWN kd;
            memset(&kd, 0, sizeof kd);
            kd.hdr.code = LVN_KEYDOWN;
            kd.hdr.hwndFrom = list->getHandle();
            if (result == ID_MENU_COPY)
                kd.wVKey = 'C';
            else if (result == ID_MENU_PASTE)
                kd.wVKey = 'V';
            else if (result == ID_MENU_DELETE)
                kd.wVKey = VK_DELETE;
            else if (result == ID_MENU_RENAME)
                kd.wVKey = VK_F2;
            onMessage(WM_NOTIFY, VK_CONTROL, (uint32) &kd);
        }
        break;
        case ID_MENU_FOLDER:
        {
            String newdir = "New Folder";
            String fulldir = String::buildFullName(path, newdir);
            FileInfo fi;
            for (int num = 1; pathFileExists(fulldir); num++)
            {
                newdir = String::format("New Folder (%d)", num);
                fulldir = String::buildFullName(path, newdir);
            }
            if (CreateDirectory(fulldir, NULL))
            {
                int pos = list->addItem(newdir,
                                        getApp()->getImageLibrary()->getListIndex("IconClosedFolder"), items.length());
                ViewItem& item = items.push();
                item.path = fulldir;
                item.pos = pos;
                item.type = ITEM_FOLDER;
                ListView_EditLabel(list->getHandle(), pos);
            }
        }
        break;
        }
    }
    break;
    case WM_NOTIFY:
    {
        NMHDR* pnm = (NMHDR*) lParam;
        if (pnm->code == LVN_ITEMACTIVATE)
        {
            NMITEMACTIVATE* pia = (NMITEMACTIVATE*) pnm;
            int pos = -1;
            if (pia->iItem >= 0)
                pos = list->getItemParam(pia->iItem);
            if (pos >= 0 && pos < items.length())
            {
                if (items[pos].type == ITEM_UPFOLDER || items[pos].type == ITEM_FOLDER)
                    mainWnd->pushView(new FolderViewItem(items[pos].path));
                else if (items[pos].type == ITEM_REPLAY)
                    mainWnd->pushView(new ReplayViewItem(items[pos].path));
            }
        }
        else if (pnm->code == LVN_BEGINDRAG)
        {
            Array<String> sel;
            getSelList(sel);
            if (sel.length())
            {
                HGLOBAL data = CreateFileDrop(sel);
                if (data)
                {
                    selfDrag = true;
                    DoDragDrop(CF_HDROP, data, DROPEFFECT_MOVE | DROPEFFECT_COPY | DROPEFFECT_LINK);
                    selfDrag = false;
                }
            }
            return TRUE;
        }
        else if (pnm->code == LVN_BEGINLABELEDIT)
        {
            NMLVDISPINFO* di = (NMLVDISPINFO*) lParam;
            int pos = -1;
            if (di->item.iItem >= 0)
                pos = list->getItemParam(di->item.iItem);
            if (pos >= 0 && pos < items.length() &&
                    (items[pos].type == ITEM_FOLDER || items[pos].type == ITEM_REPLAY))
                return FALSE;
            return TRUE;
        }
        else if (pnm->code == LVN_ENDLABELEDIT)
        {
            NMLVDISPINFO* di = (NMLVDISPINFO*) lParam;
            int pos = -1;
            if (di->item.iItem >= 0)
                pos = list->getItemParam(di->item.iItem);
            if (di->item.pszText && pos >= 0 && pos < items.length() &&
                    (items[pos].type == ITEM_FOLDER || items[pos].type == ITEM_REPLAY))
            {
                String src = items[pos].path;
                String dst = String::buildFullName(String::getPath(src), di->item.pszText);
                src += '\0';
                if (items[pos].type == ITEM_REPLAY)
                    dst += ".w3g";
                dst += '\0';
                SHFILEOPSTRUCT op;
                memset(&op, 0, sizeof op);
                op.wFunc = FO_RENAME;
                op.pFrom = src;
                op.pTo = dst;
                if (SHFileOperationEx(&op) == 0)
                {
                    items[pos].path = String::buildFullName(String::getPath(items[pos].path), di->item.pszText);
                    if (items[pos].type == ITEM_REPLAY)
                        items[pos].path += ".w3g";
                    return TRUE;
                }
            }
            rebuild();
            return FALSE;
        }
        else if (pnm->code == LVN_COLUMNCLICK)
        {
            NMLISTVIEW* lv = (NMLISTVIEW*) lParam;
            bool colShow[colCount] = {true,
                                      cfg.selColumns & COL_SAVED,
                                      cfg.selColumns & COL_SIZE,
                                      cfg.selColumns & COL_NAME,
                                      cfg.selColumns & COL_RATIO,
                                      cfg.selColumns & COL_LENGTH,
                                      cfg.selColumns & COL_MODE
                                     };
            int col = lv->iSubItem;
            for (int i = 0; i < col && col < colCount - 1; i++)
                if (!colShow[i])
                    col++;
            int pos = 0;
            while (pos < colCount - 1 && cfg.colSort[pos] != col && cfg.colSort[pos] != ~col)
                pos++;
            if (pos == 0)
                cfg.colSort[0] = ~cfg.colSort[0];
            else
            {
                for (int i = pos; i > 0; i--)
                    cfg.colSort[i] = cfg.colSort[i - 1];
                cfg.colSort[0] = col;
            }
            rebuild();
        }
        else if (pnm->code == HDN_ENDDRAG)
            PostMessage(list->getHandle(), WM_POSTHEADERDRAG, 0, 0);
        else if (pnm->code == HDN_ENDTRACK)
        {
            NMHEADER* nhdr = (NMHEADER*) pnm;
            bool colShow[colCount] = {true,
                                      cfg.selColumns & COL_SAVED,
                                      cfg.selColumns & COL_SIZE,
                                      cfg.selColumns & COL_NAME,
                                      cfg.selColumns & COL_RATIO,
                                      cfg.selColumns & COL_LENGTH,
                                      cfg.selColumns & COL_MODE
                                     };
            int count = 0;
            int colUnpos[colCount];
            for (int i = 0; i < colCount; i++)
                if (colShow[i])
                    colUnpos[count++] = i;
            if (nhdr->iItem >= 0 && nhdr->iItem < count &&
                    nhdr->pitem && nhdr->pitem->mask & HDI_WIDTH)
            {
                int col = colUnpos[nhdr->iItem];
                cfg.colWidth[col] = nhdr->pitem->cxy;
            }
        }
        else if (pnm->code == LVN_KEYDOWN)
        {
            NMLVKEYDOWN* kd = (NMLVKEYDOWN*) lParam;
            bool controlKey = ((GetAsyncKeyState(VK_CONTROL) & 0x8000) || wParam == VK_CONTROL);
            if (kd->wVKey == 'C' && controlKey)
            {
                Array<String> sel;
                getSelList(sel);
                if (sel.length())
                {
                    HGLOBAL hDrop = CreateFileDrop(sel);
                    SetClipboard(CF_HDROP, hDrop);
                }
            }
            else if (kd->wVKey == 'V' && controlKey)
            {
                ClipboardReader clip(CF_HDROP);
                HGLOBAL hDrop = clip.getData();
                if (hDrop)
                    doPaste(hDrop, DROPEFFECT_COPY, path);
            }
            else if (kd->wVKey == VK_DELETE)
            {
                Array<String> sel;
                getSelList(sel);
                if (sel.length())
                {
                    char* str = FileListToString(sel);
                    SHFILEOPSTRUCT fileop;
                    memset(&fileop, 0, sizeof fileop);
                    fileop.wFunc = FO_DELETE;
                    fileop.pFrom = str;
                    SHFileOperationEx(&fileop);
                }
            }
            else if (kd->wVKey == VK_F2)
            {
                SetFocus(list->getHandle());
                int sel = ListView_GetNextItem(list->getHandle(), -1, LVNI_FOCUSED);
                if (sel < 0)
                    sel = 0;
                ListView_EditLabel(list->getHandle(), sel);
            }
        }
    }
    break;
    case WM_DRAGOVER:
    case WM_DRAGLEAVE:
    {
        LVHITTESTINFO ht;
        LVITEM lvi;
        memset(&lvi, 0, sizeof lvi);
        if (message == WM_DRAGOVER)
        {
            ht.pt.x = LOWORD(lParam);
            ht.pt.y = HIWORD(lParam);
            ListView_HitTest(list->getHandle(), &ht);
            if (ht.iItem >= 0)
            {
                lvi.iItem = ht.iItem;
                lvi.mask = LVIF_PARAM | LVIF_STATE;
                lvi.stateMask = LVIS_SELECTED;
                ListView_GetItem(list->getHandle(), &lvi);
                if (lvi.lParam < 0 || lvi.lParam >= items.length() ||
                        (items[lvi.lParam].type != ITEM_UPFOLDER && items[lvi.lParam].type != ITEM_FOLDER))
                    ht.iItem = -1;
                if (selfDrag && (lvi.state & LVIS_SELECTED))
                    ht.iItem = -1;
            }
            if (wParam && selfDrag && ht.iItem == -1 && *(DWORD*) wParam == DROPEFFECT_MOVE)
                *(DWORD*) wParam = DROPEFFECT_NONE;
        }
        else
            ht.iItem = -1;
        if (ht.iItem != list->highlight)
        {
            lvi.mask = LVIF_STATE;
            lvi.stateMask = LVIS_DROPHILITED;
            if (list->highlight >= 0)
            {
                lvi.iItem = list->highlight;
                ListView_SetItem(list->getHandle(), &lvi);
            }
            if (ht.iItem >= 0)
            {
                lvi.state = LVIS_DROPHILITED;
                lvi.iItem = ht.iItem;
                ListView_SetItem(list->getHandle(), &lvi);
            }
            list->highlight = ht.iItem;
        }
    }
    break;
    case WM_DRAGDROP:
        if (lParam == DROPEFFECT_MOVE || lParam == DROPEFFECT_COPY)
        {
            String opTo = path;
            if (list->highlight >= 0)
            {
                int param = list->getItemParam(list->highlight);
                if (param >= 0 && param < items.length() &&
                        (items[param].type == ITEM_UPFOLDER || items[param].type == ITEM_FOLDER))
                    opTo = items[param].path;
            }
            doPaste((HGLOBAL) wParam, lParam, opTo);
        }
        return 0;
    case WM_POSTHEADERDRAG:
    {
        bool colShow[colCount] = {true,
                                  cfg.selColumns & COL_SAVED,
                                  cfg.selColumns & COL_SIZE,
                                  cfg.selColumns & COL_NAME,
                                  cfg.selColumns & COL_RATIO,
                                  cfg.selColumns & COL_LENGTH,
                                  cfg.selColumns & COL_MODE
                                 };
        int count = 0;
        int colUnpos[colCount];
        for (int i = 0; i < colCount; i++)
            if (colShow[i])
                colUnpos[count++] = i;
        int colOrder[colCount];
        ListView_GetColumnOrderArray(list->getHandle(), count, colOrder);
        int pos = 0;
        for (int i = 0; i < colCount; i++)
            if (colShow[cfg.colOrder[i]])
                cfg.colOrder[i] = colUnpos[colOrder[pos++]];
    }
    break;
    case WM_REBUILDLIST:
        if (ListView_GetEditControl(list->getHandle()) == NULL)
            rebuild();
        break;
    case WM_UPDATELISTITEM:
        updateListItem(wParam, lParam);
        break;
    default:
        return M_UNHANDLED;
    }
    return 0;
}
history_return_type History::ProcessMenu(string &strStr, GUID* Guid, string *pstrFile, string *pstrData, const wchar_t *Title, VMenu2 &HistoryMenu, int Height, history_record_type &Type, Dialog *Dlg)
{
	unsigned __int64 SelectedRecord = 0;
	string strSelectedRecordName,strSelectedRecordGuid,strSelectedRecordFile,strSelectedRecordData;
	history_record_type SelectedRecordType = HR_DEFAULT;
	FarListPos Pos={sizeof(FarListPos)};
	int MenuExitCode=-1;
	history_return_type RetCode = HRT_ENTER;
	bool Done=false;
	bool SetUpMenuPos=false;

	if (m_TypeHistory == HISTORYTYPE_DIALOG && !HistoryCfgRef()->Count(m_TypeHistory,m_HistoryName))
		return HRT_CANCEL;

	while (!Done)
	{
		bool IsUpdate=false;
		HistoryMenu.DeleteItems();
		{
			bool bSelected=false;
			DWORD index=0;
			string strHName,strHGuid,strHFile,strHData;
			history_record_type HType;
			bool HLock;
			unsigned __int64 id;
			unsigned __int64 Time;
			SYSTEMTIME st;
			GetLocalTime(&st);
			int LastDay=0, LastMonth = 0, LastYear = 0;

			const auto GetTitle = [](history_record_type Type) -> const wchar_t*
			{
				switch (Type)
				{
				case HR_VIEWER:
					return MSG(MHistoryView);
				case HR_EDITOR:
				case HR_EDITOR_RO:
					return MSG(MHistoryEdit);
				case HR_EXTERNAL:
				case HR_EXTERNAL_WAIT:
					return MSG(MHistoryExt);
				}

				return L"";
			};

			while (HistoryCfgRef()->Enum(index++,m_TypeHistory,m_HistoryName,&id,strHName,&HType,&HLock,&Time,strHGuid,strHFile,strHData,m_TypeHistory==HISTORYTYPE_DIALOG))
			{
				string strRecord;

				if (m_TypeHistory == HISTORYTYPE_VIEW)
					strRecord = GetTitle(HType) + string(L":") + (HType == HR_EDITOR_RO ? L"-" : L" ");

				else if (m_TypeHistory == HISTORYTYPE_FOLDER)
				{
					GUID HGuid;
					if(StrToGuid(strHGuid,HGuid) &&  HGuid != FarGuid)
					{
						Plugin *pPlugin = Global->CtrlObject->Plugins->FindPlugin(HGuid);
						strRecord = (pPlugin ? pPlugin->GetTitle() : L"{" + strHGuid + L"}") + L":";
						if(!strHFile.empty())
							strRecord += strHFile + L":";
					}
				}
				auto FTTime = UI64ToFileTime(Time);
				SYSTEMTIME SavedTime;
				Utc2Local(FTTime, SavedTime);
				if(LastDay != SavedTime.wDay || LastMonth != SavedTime.wMonth || LastYear != SavedTime.wYear)
				{
					LastDay = SavedTime.wDay;
					LastMonth = SavedTime.wMonth;
					LastYear = SavedTime.wYear;
					MenuItemEx Separator;
					Separator.Flags = LIF_SEPARATOR;
					string strTime;
					ConvertDate(FTTime, Separator.strName, strTime, 5, FALSE, FALSE, TRUE);
					HistoryMenu.AddItem(Separator);
				}
				strRecord += strHName;

				if (m_TypeHistory != HISTORYTYPE_DIALOG)
					ReplaceStrings(strRecord, L"&", L"&&");

				MenuItemEx MenuItem(strRecord);
				MenuItem.SetCheck(HLock?1:0);

				if (!SetUpMenuPos && m_CurrentItem==id)
				{
					MenuItem.SetSelect(TRUE);
					bSelected=true;
				}

				HistoryMenu.SetUserData(&id,sizeof(id),HistoryMenu.AddItem(MenuItem));
			}

			if (!SetUpMenuPos && !bSelected && m_TypeHistory!=HISTORYTYPE_DIALOG)
			{
				FarListPos p={sizeof(FarListPos)};
				p.SelectPos = HistoryMenu.GetItemCount()-1;
				p.TopPos = 0;
				HistoryMenu.SetSelectPos(&p);
			}
		}

		if (m_TypeHistory == HISTORYTYPE_DIALOG)
		{
			int X1,Y1,X2,Y2;
			Dlg->CalcComboBoxPos(nullptr, HistoryMenu.GetItemCount(), X1, Y1, X2, Y2);
			HistoryMenu.SetPosition(X1, Y1, X2, Y2);
		}
		else
			HistoryMenu.SetPosition(-1,-1,0,0);

		if (SetUpMenuPos)
		{
			Pos.SelectPos=Pos.SelectPos < HistoryMenu.GetItemCount() ? Pos.SelectPos : HistoryMenu.GetItemCount()-1;
			Pos.TopPos=std::min(Pos.TopPos,HistoryMenu.GetItemCount()-Height);
			HistoryMenu.SetSelectPos(&Pos);
			SetUpMenuPos=false;
		}

		if(m_TypeHistory == HISTORYTYPE_DIALOG && !HistoryMenu.GetItemCount())
			return HRT_CANCEL;

		MenuExitCode=HistoryMenu.Run([&](const Manager::Key& RawKey)->int
		{
			const auto Key=RawKey.FarKey();
			if (m_TypeHistory == HISTORYTYPE_DIALOG && Key==KEY_TAB) // Tab в списке хистори диалогов - аналог Enter
			{
				HistoryMenu.Close();
				return 1;
			}

			HistoryMenu.GetSelectPos(&Pos);
			void* Data = HistoryMenu.GetUserData(nullptr, 0,Pos.SelectPos);
			unsigned __int64 CurrentRecord = Data? *static_cast<unsigned __int64*>(Data) : 0;
			int KeyProcessed = 1;

			switch (Key)
			{
				case KEY_CTRLR: // обновить с удалением недоступных
				case KEY_RCTRLR:
				{
					if (m_TypeHistory == HISTORYTYPE_FOLDER || m_TypeHistory == HISTORYTYPE_VIEW)
					{
						bool ModifiedHistory=false;

						SCOPED_ACTION(auto) = HistoryCfgRef()->ScopedTransaction();

						DWORD index=0;
						string strHName,strHGuid,strHFile,strHData;
						history_record_type HType;
						bool HLock;
						unsigned __int64 id;
						unsigned __int64 Time;
						while (HistoryCfgRef()->Enum(index++,m_TypeHistory,m_HistoryName,&id,strHName,&HType,&HLock,&Time,strHGuid,strHFile,strHData))
						{
							if (HLock) // залоченные не трогаем
								continue;

							// убить запись из истории
							bool kill=false;
							GUID HGuid;
							if(StrToGuid(strHGuid,HGuid) && HGuid != FarGuid)
							{
								if (!Global->CtrlObject->Plugins->FindPlugin(HGuid))
									kill=true;
								else if (!strHFile.empty() && !os::fs::exists(strHFile))
									kill=true;
							}
							else if (!os::fs::exists(strHName))
								kill=true;

							if(kill)
							{
								HistoryCfgRef()->Delete(id);
								ModifiedHistory=true;
							}
						}

						if (ModifiedHistory) // избавляемся от лишних телодвижений
						{
							IsUpdate=true;
							HistoryMenu.Close(Pos.SelectPos);
						}

						ResetPosition();
					}

					break;
				}
				case KEY_CTRLSHIFTNUMENTER:
				case KEY_RCTRLSHIFTNUMENTER:
				case KEY_CTRLNUMENTER:
				case KEY_RCTRLNUMENTER:
				case KEY_SHIFTNUMENTER:
				case KEY_CTRLSHIFTENTER:
				case KEY_RCTRLSHIFTENTER:
				case KEY_CTRLENTER:
				case KEY_RCTRLENTER:
				case KEY_SHIFTENTER:
				case KEY_CTRLALTENTER:
				case KEY_RCTRLRALTENTER:
				case KEY_CTRLRALTENTER:
				case KEY_RCTRLALTENTER:
				case KEY_CTRLALTNUMENTER:
				case KEY_RCTRLRALTNUMENTER:
				case KEY_CTRLRALTNUMENTER:
				case KEY_RCTRLALTNUMENTER:
				{
					if (m_TypeHistory == HISTORYTYPE_DIALOG)
						break;

					HistoryMenu.Close(Pos.SelectPos);
					Done=true;
					RetCode = (Key==KEY_CTRLALTENTER||Key==KEY_RCTRLRALTENTER||Key==KEY_CTRLRALTENTER||Key==KEY_RCTRLALTENTER||
							Key==KEY_CTRLALTNUMENTER||Key==KEY_RCTRLRALTNUMENTER||Key==KEY_CTRLRALTNUMENTER||Key==KEY_RCTRLALTNUMENTER)? HRT_CTRLALTENTER
							:((Key==KEY_CTRLSHIFTENTER||Key==KEY_RCTRLSHIFTENTER||Key==KEY_CTRLSHIFTNUMENTER||Key==KEY_RCTRLSHIFTNUMENTER)? HRT_CTRLSHIFTENTER
							:((Key==KEY_SHIFTENTER||Key==KEY_SHIFTNUMENTER)? HRT_SHIFTETNER
							:HRT_CTRLENTER));
					break;
				}
				case KEY_F3:
				case KEY_F4:
				case KEY_NUMPAD5:  case KEY_SHIFTNUMPAD5:
				{
					if (m_TypeHistory != HISTORYTYPE_VIEW)
						break;

					HistoryMenu.Close(Pos.SelectPos);
					Done=true;
					RetCode=(Key==KEY_F4? HRT_F4 : HRT_F3);
					break;
				}
				// $ 09.04.2001 SVS - Фича - копирование из истории строки в Clipboard
				case KEY_CTRLC:
				case KEY_RCTRLC:
				case KEY_CTRLINS:  case KEY_CTRLNUMPAD0:
				case KEY_RCTRLINS: case KEY_RCTRLNUMPAD0:
				{
					if (CurrentRecord)
					{
						string strName;
						if (HistoryCfgRef()->Get(CurrentRecord, strName))
							SetClipboard(strName);
					}

					break;
				}
				// Lock/Unlock
				case KEY_INS:
				case KEY_NUMPAD0:
				{
					if (CurrentRecord)
					{
						HistoryCfgRef()->FlipLock(CurrentRecord);
						ResetPosition();
						HistoryMenu.Close(Pos.SelectPos);
						IsUpdate=true;
						SetUpMenuPos=true;
					}

					break;
				}
				case KEY_SHIFTNUMDEL:
				case KEY_SHIFTDEL:
				{
					if (CurrentRecord && !HistoryCfgRef()->IsLocked(CurrentRecord))
					{
						HistoryCfgRef()->Delete(CurrentRecord);
						ResetPosition();
						HistoryMenu.Close(Pos.SelectPos);
						IsUpdate=true;
						SetUpMenuPos=true;
					}

					break;
				}
				case KEY_NUMDEL:
				case KEY_DEL:
				{
					if (HistoryMenu.GetItemCount() &&
					        (!Global->Opt->Confirm.HistoryClear ||
					         (Global->Opt->Confirm.HistoryClear &&
					          !Message(MSG_WARNING,2,
					                  MSG((m_TypeHistory==HISTORYTYPE_CMD || m_TypeHistory==HISTORYTYPE_DIALOG?MHistoryTitle:
					                       (m_TypeHistory==HISTORYTYPE_FOLDER?MFolderHistoryTitle:MViewHistoryTitle))),
					                  MSG(MHistoryClear),
					                  MSG(MClear),MSG(MCancel)))))
					{
						HistoryCfgRef()->DeleteAllUnlocked(m_TypeHistory,m_HistoryName);

						ResetPosition();
						HistoryMenu.Close(Pos.SelectPos);
						IsUpdate=true;
					}

					break;
				}

				default:
					KeyProcessed = 0;
			}
			return KeyProcessed;
		});

		if (IsUpdate)
			continue;

		Done=true;

		if (MenuExitCode >= 0)
		{
			SelectedRecord = *static_cast<unsigned __int64*>(HistoryMenu.GetUserData(nullptr, 0, MenuExitCode));

			if (!SelectedRecord)
				return HRT_CANCEL;

			if (!HistoryCfgRef()->Get(SelectedRecord, strSelectedRecordName, &SelectedRecordType, strSelectedRecordGuid, strSelectedRecordFile, strSelectedRecordData))
				return HRT_CANCEL;

			#if 1
			//Maximus: для сетевых ресурсов - танцы с бубном
			if (Global->Opt->RemoteAutoLogin
				&& SelectedRecordType != HR_EXTERNAL && SelectedRecordType != HR_EXTERNAL_WAIT // ignore external
				&& RetCode != HRT_CTRLENTER && ((m_TypeHistory == HISTORYTYPE_FOLDER && strSelectedRecordGuid.empty()) || m_TypeHistory == HISTORYTYPE_VIEW))
			{
				size_t DirOffset = 0;
				PATH_TYPE Type = ParsePath(strSelectedRecordName, &DirOffset);
				string strCopy = DirOffset ? strSelectedRecordName.substr(0, DirOffset) : strSelectedRecordName.data();
				if (Type == PATH_REMOTE /*|| Type == PATH_REMOTEUNC*/)
				{
					auto DE = std::make_unique<elevation::suppress>();
					if (os::GetFileAttributes(strSelectedRecordName) == INVALID_FILE_ATTRIBUTES)
					{
						FarMacroValue vParams[2]={L"connect",strCopy.data()};
						OpenMacroInfo info={sizeof(OpenMacroInfo),2,vParams};
						void* CallResult = nullptr; //we must pass (&CallResult) to avoid memory leak
						Global->CtrlObject->Plugins->CallPlugin(Global->Opt->KnownIDs.Network.Id, OPEN_FROMMACRO, &info, &CallResult);
						//CallResult==1 on succeess?
					}
				}
			}
			//Maximus: поплясали - теперь как обычно
			if (SelectedRecordType != HR_EXTERNAL && SelectedRecordType != HR_EXTERNAL_WAIT
				&& RetCode != HRT_CTRLENTER && ((m_TypeHistory == HISTORYTYPE_FOLDER && strSelectedRecordGuid.empty()) || m_TypeHistory == HISTORYTYPE_VIEW) && !os::fs::exists(strSelectedRecordName))
			#else
			if (SelectedRecordType != HR_EXTERNAL && SelectedRecordType != HR_EXTERNAL_WAIT
				&& RetCode != HRT_CTRLENTER && ((m_TypeHistory == HISTORYTYPE_FOLDER && strSelectedRecordGuid.empty()) || m_TypeHistory == HISTORYTYPE_VIEW) && !os::fs::exists(strSelectedRecordName))
			#endif
			{
				SetLastError(ERROR_FILE_NOT_FOUND);
				Global->CatchError();

				if (SelectedRecordType == HR_EDITOR && m_TypeHistory == HISTORYTYPE_VIEW) // Edit? тогда спросим и если надо создадим
				{
					if (!Message(MSG_WARNING|MSG_ERRORTYPE,2,Title,strSelectedRecordName.data(),MSG(MViewHistoryIsCreate),MSG(MHYes),MSG(MHNo)))
						break;
				}
				else
				{
					Message(MSG_WARNING|MSG_ERRORTYPE,1,Title,strSelectedRecordName.data(),MSG(MOk));
				}

				Done=false;
				SetUpMenuPos=true;
				continue;
			}
		}
	}

	if (MenuExitCode < 0 || !SelectedRecord)
		return HRT_CANCEL;

	if (m_KeepSelectedPos)
	{
		m_CurrentItem = SelectedRecord;
	}

	strStr = strSelectedRecordName;
	if(Guid)
	{
		if(!StrToGuid(strSelectedRecordGuid,*Guid)) *Guid = FarGuid;
	}
	if(pstrFile) *pstrFile = strSelectedRecordFile;
	if(pstrData) *pstrData = strSelectedRecordData;

	switch(RetCode)
	{
	case HRT_CANCEL:
		break;

	case HRT_ENTER:
	case HRT_SHIFTETNER:
	case HRT_CTRLENTER:
	case HRT_CTRLSHIFTENTER:
	case HRT_CTRLALTENTER:
		Type = SelectedRecordType;
		break;

	case HRT_F3:
		Type = HR_VIEWER;
		RetCode = HRT_ENTER;
		break;

	case HRT_F4:
		Type = HR_EDITOR;
		if (SelectedRecordType == HR_EDITOR_RO)
			Type = HR_EDITOR_RO;
		RetCode = HRT_ENTER;
		break;
	}
	return RetCode;
}
uint32 SearchResults::onMessage(uint32 message, uint32 wParam, uint32 lParam)
{
  switch (message)
  {
  case WM_ADDFILE:
    EnterCriticalSection(&lock);
    while (getCount() < items.length())
      addItem(getCount(), true);
    LeaveCriticalSection(&lock);
    return 0;
  case WM_NOTIFY:
    {
      NMHDR* pnm = (NMHDR*) lParam;
      if (pnm->code == LVN_ITEMACTIVATE)
      {
        NMITEMACTIVATE* pia = (NMITEMACTIVATE*) pnm;
        if (pia->iItem >= 0 && pia->iItem < items.length())
        {
          SendMessage(getApp()->getMainWindow(), WM_PUSHVIEW,
            (uint32) new ReplayViewItem(items[pia->iItem].path), 0);
        }
        return 0;
      }
      else if (pnm->code == LVN_BEGINDRAG)
      {
        Array<String> sel;
        getSelList(sel);
        if (sel.length())
        {
          HGLOBAL data = CreateFileDrop(sel);
          if (data)
            DoDragDrop(CF_HDROP, data, DROPEFFECT_MOVE | DROPEFFECT_COPY | DROPEFFECT_LINK);
        }
        return TRUE;
      }
      else if (pnm->code == LVN_COLUMNCLICK)
      {
        NMLISTVIEW* lv = (NMLISTVIEW*) lParam;
        bool colShow[colCount] = {true,
          cfg.selColumns & COL_SAVED,
          cfg.selColumns & COL_SIZE,
          cfg.selColumns & COL_NAME,
          cfg.selColumns & COL_RATIO,
          cfg.selColumns & COL_LENGTH,
          cfg.selColumns & COL_MODE
        };
        int col = lv->iSubItem;
        for (int i = 0; i < col && col < colCount - 1; i++)
          if (!colShow[i])
            col++;
        int pos = 0;
        while (pos < colCount - 1 && cfg.colSort[pos] != col && cfg.colSort[pos] != ~col)
          pos++;
        if (pos == 0)
          cfg.colSort[0] = ~cfg.colSort[0];
        else
        {
          for (int i = pos; i > 0; i--)
            cfg.colSort[i] = cfg.colSort[i - 1];
          cfg.colSort[0] = col;
        }
        rebuild();
      }
      else if (pnm->code == HDN_ENDDRAG)
        PostMessage(hWnd, WM_POSTHEADERDRAG, 0, 0);
      else if (pnm->code == HDN_ENDTRACK)
      {
        NMHEADER* nhdr = (NMHEADER*) pnm;
        bool colShow[colCount] = {true,
          cfg.selColumns & COL_SAVED,
          cfg.selColumns & COL_SIZE,
          cfg.selColumns & COL_NAME,
          cfg.selColumns & COL_RATIO,
          cfg.selColumns & COL_LENGTH,
          cfg.selColumns & COL_MODE
        };
        int count = 0;
        int colUnpos[colCount];
        for (int i = 0; i < colCount; i++)
          if (colShow[i])
            colUnpos[count++] = i;
        if (nhdr->iItem >= 0 && nhdr->iItem < count &&
          nhdr->pitem && nhdr->pitem->mask & HDI_WIDTH)
        {
          int col = colUnpos[nhdr->iItem];
          cfg.colWidth[col] = nhdr->pitem->cxy;
        }
      }
      else if (pnm->code == LVN_KEYDOWN)
      {
        NMLVKEYDOWN* kd = (NMLVKEYDOWN*) lParam;
        bool controlKey = ((GetAsyncKeyState(VK_CONTROL) & 0x8000) || wParam == VK_CONTROL);
        if (kd->wVKey == 'C' && controlKey)
        {
          Array<String> sel;
          getSelList(sel);
          if (sel.length())
          {
            HGLOBAL hDrop = CreateFileDrop(sel);
            SetClipboard(CF_HDROP, hDrop);
          }
        }
        else if (kd->wVKey == VK_DELETE)
        {
          Array<String> sel;
          getSelList(sel);
          if (sel.length())
          {
            char* str = FileListToString(sel);
            SHFILEOPSTRUCT fileop;
            memset(&fileop, 0, sizeof fileop);
            fileop.wFunc = FO_DELETE;
            fileop.pFrom = str;
            SHFileOperationEx(&fileop);
          }
        }
        return 0;
      }
    }
    break;
  case WM_POSTHEADERDRAG:
    {
      bool colShow[colCount] = {true,
        cfg.selColumns & COL_SAVED,
        cfg.selColumns & COL_SIZE,
        cfg.selColumns & COL_NAME,
        cfg.selColumns & COL_RATIO,
        cfg.selColumns & COL_LENGTH,
        cfg.selColumns & COL_MODE
      };
      int count = 0;
      int colUnpos[colCount];
      for (int i = 0; i < colCount; i++)
        if (colShow[i])
          colUnpos[count++] = i;
      int colOrder[colCount];
      ListView_GetColumnOrderArray(hWnd, count, colOrder);
      int pos = 0;
      for (int i = 0; i < colCount; i++)
        if (colShow[cfg.colOrder[i]])
          cfg.colOrder[i] = colUnpos[colOrder[pos++]];
    }
    return 0;
  }
  return ListFrame::onMessage(message, wParam, lParam);
}
Exemple #10
0
void TimeEdit::CopyTime() {
    SetClipboard(from_wx(GetValue()));
}
Exemple #11
0
uint32 Editor::onMessage(uint32 message, uint32 wParam, uint32 lParam)
{
  switch (message)
  {
  case WM_DESTROY:
    delete target;
    target = NULL;
    break;
  case WM_SETCURSOR:
    if (LOWORD(lParam) == HTCLIENT)
    {
      POINT pt;
      GetCursorPos(&pt);
      ScreenToClient(hWnd, &pt);
      if (pt.x < LeftMargin())
        SetCursor(cursors[cArrow]);
      else if (selStart != caret)
      {
        pt.x = (pt.x - LeftMargin()) / chSize.cx + scrollPos.x;
        pt.y = pt.y / chSize.cy + scrollPos.y;
        if (pt.y < 0 || pt.y >= lines.length() || pt.x < 0 || pt.x >= lines[pt.y].text.length())
          SetCursor(cursors[cBeam]);
        else
        {
          int offset = fromPoint(pt);
          int sela = (selStart < caret ? selStart : caret);
          int selb = (selStart < caret ? caret : selStart);
          if (offset >= sela && offset < selb)
            SetCursor(cursors[cArrow]);
          else
            SetCursor(cursors[cBeam]);
        }
      }
      else
        SetCursor(cursors[cBeam]);
    }
    else
      SetCursor(cursors[cArrow]);
    return TRUE;
  case WM_ERASEBKGND:
    return TRUE;
  case WM_PAINT:
    paint();
    return 0;
  case WM_SIZE:
    if (hBitmap)
    {
      int wd = LOWORD(lParam);
      int ht = HIWORD(lParam);
      if (wd < 10) wd = 10;
      if (ht < 10) ht = 10;
      hBitmap = CreateCompatibleBitmap(hDC, wd, ht);
      SelectObject(hDC, hBitmap);
    }
    updateExtent();
    return 0;
  case WM_SETFOCUS:
    placeCaret();
    invalidate();
    getParent()->notify(EN_FOCUSED, (uint32) this, 0);
    return 0;
  case WM_KILLFOCUS:
    DestroyCaret();
    updateCaret();
    invalidate();
    return 0;
  case WM_LBUTTONDBLCLK:
    {
      POINT pt = paramToPoint(lParam);
      fixPoint(pt);
      int ptStart = wordEnd(lines[pt.y].text.c_str(), pt.x, -1);
      int ptEnd = wordEnd(lines[pt.y].text.c_str(), pt.x, 1);
      int offset = fromPoint(pt);
      selStart = offset - (pt.x - ptStart);
      caret = offset + (ptEnd - pt.x);
      updateCaret();
    }
    return 0;
  case WM_LBUTTONDOWN:
    if (int(GET_X_LPARAM(lParam)) < int(settings->bpOffset - scrollPos.x * chSize.cx))
    {
      POINT pt = paramToPoint(lParam);
      toggleBreakpoint(pt.y);
    }
    else
    {
      POINT pt = paramToPoint(lParam);
      int offset = fromPoint(pt);
      int sela = (selStart < caret ? selStart : caret);
      int selb = (selStart > caret ? selStart : caret);
      if (offset >= sela && offset < selb)
      {
        dragop = 1;
        uint32 fx = DoDragDropEx(CF_UNICODETEXT, CreateGlobalText(getSelection()),
            DROPEFFECT_MOVE | DROPEFFECT_COPY, hWnd);
        if (fx == DROPEFFECT_NONE)
          dragop = 0;
        //else if (fx != DROPEFFECT_COPY && dragop != 2)
        //  replace(sela, selb, "");
      }
      else
        SetCapture(hWnd);
      if (dragop == 0)
      {
        caret = offset;
        if (!(wParam & MK_SHIFT))
          selStart = caret;
      }
      dragop = 0;
      if (GetFocus() != hWnd)
        SetFocus(hWnd);
      updateCaret();
    }
    return 0;
  case WM_RBUTTONDOWN:
    if (int(GET_X_LPARAM(lParam)) >= int(settings->bpOffset - scrollPos.x * chSize.cx))
    {
      POINT pt = paramToPoint(lParam);
      int offset = fromPoint(pt);
      int sela = (selStart < caret ? selStart : caret);
      int selb = (selStart > caret ? selStart : caret);
      if (offset < sela || offset >= selb)
        caret = selStart = offset;
      if (GetFocus() != hWnd)
        SetFocus(hWnd);
      updateCaret();
    }
    return 0;
  case WM_MOUSEMOVE:
    if (GetCapture() == hWnd && (wParam & MK_LBUTTON))
    {
      POINT pt = paramToPoint(lParam);
      caret = fromPoint(pt);
      updateCaret();
    }
    return 0;
  case WM_LBUTTONUP:
    ReleaseCapture();
    return 0;
  case WM_CHAR:
    if (iswprint(wParam) && (GetAsyncKeyState(VK_CONTROL) & 0x8000) == 0)
    {
      if (caret == selStart && !insertMode && caret < getTextLength())
        replace(caret, caret + 1, WideString((wchar_t) wParam));
      else
        replace(selStart, caret, WideString((wchar_t) wParam));
    }
    return 0;
  case WM_VSCROLL:
    {
      SCROLLINFO si;
      memset(&si, 0, sizeof si);
      si.cbSize = sizeof si;
      si.fMask = SIF_ALL;
      GetScrollInfo(hWnd, SB_VERT, &si);
      switch (LOWORD(wParam))
      {
      case SB_TOP:
        si.nPos = si.nMin;
        break;
      case SB_BOTTOM:
        si.nPos = si.nMax;
        break;
      case SB_LINEUP:
        si.nPos--;
        break;
      case SB_LINEDOWN:
        si.nPos++;
        break;
      case SB_PAGEUP:
        si.nPos -= si.nPage;
        break;
      case SB_PAGEDOWN:
        si.nPos += si.nPage;
        break;
      case SB_THUMBTRACK:
        si.nPos = si.nTrackPos;
        break;
      }
      doScroll(scrollPos.x, si.nPos);
    }
    return 0;
  case WM_HSCROLL:
    {
      SCROLLINFO si;
      memset(&si, 0, sizeof si);
      si.cbSize = sizeof si;
      si.fMask = SIF_ALL;
      GetScrollInfo(hWnd, SB_HORZ, &si);
      switch (LOWORD(wParam))
      {
      case SB_LEFT:
        si.nPos = si.nMin;
        break;
      case SB_RIGHT:
        si.nPos = si.nMax;
        break;
      case SB_LINELEFT:
        si.nPos--;
        break;
      case SB_LINERIGHT:
        si.nPos++;
        break;
      case SB_PAGELEFT:
        si.nPos -= si.nPage;
        break;
      case SB_PAGERIGHT:
        si.nPos += si.nPage;
        break;
      case SB_THUMBTRACK:
        si.nPos = si.nTrackPos;
        break;
      }
      doScroll(si.nPos, scrollPos.y);
    }
    return 0;
  case WM_MOUSEWHEEL:
    {
      int step;
      SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &step, 0);
      if (step < 0)
        step = 3;
      scrollAccum.y += GET_WHEEL_DELTA_WPARAM(wParam) * step;
      doScroll(scrollPos.x, scrollPos.y - scrollAccum.y / WHEEL_DELTA);
      scrollAccum.y %= WHEEL_DELTA;
    }
    return 0;
  case WM_MOUSEHWHEEL:
    {
      scrollAccum.x += GET_WHEEL_DELTA_WPARAM(wParam) * 4;
      doScroll(scrollPos.x + scrollAccum.x / WHEEL_DELTA, scrollPos.y);
      scrollAccum.x %= WHEEL_DELTA;
    }
    return 0;
  case WM_DRAGOVER:
    {
      if (running || settings->mode)
        return TRUE;
      POINT pt = paramToPoint(lParam);
      dropPos = fromPoint(pt);

      RECT rc;
      GetClientRect(hWnd, &rc);
      int xto = scrollPos.x;
      if (pt.x < 10)
        xto--;
      else if (pt.x > rc.right - 10)
        xto++;
      int yto = scrollPos.y;
      if (pt.y < 10)
        yto--;
      else if (pt.y > rc.bottom - 10)
        yto++;
      doScroll(xto, yto);

      int sela = (selStart < caret ? selStart : caret);
      int selb = (selStart > caret ? selStart : caret);
      if (dropPos > sela && dropPos < selb)
        return TRUE;
      else
      {
        fixPoint(pt);
        CreateCaret(hWnd, NULL, 2, chSize.cy);
        SetCaretPos((pt.x - scrollPos.x) * chSize.cx + LeftMargin(), (pt.y - scrollPos.y) * chSize.cy);
        ShowCaret(hWnd);
      }
    }
    return 0;
  case WM_DRAGLEAVE:
    dropPos = 0;
    updateCaret();
    return 0;
  case WM_DRAGDROP:
    if (running || settings->mode)
      return DROPEFFECT_NONE;
    if (dragop)
    {
      dragop = 2;
      int sela = (selStart < caret ? selStart : caret);
      int selb = (selStart > caret ? selStart : caret);
      if (dropPos < sela || dropPos > selb)
      {
        WideString text = getSelection();
        if (lParam != DROPEFFECT_COPY)
        {
          replace(sela, selb, L"");
          if (dropPos > selb)
            dropPos -= (selb - sela);
          caret = replace(dropPos, dropPos, text, NULL, true);
        }
        else
          caret = replace(dropPos, dropPos, text);
        selStart = dropPos;
      }
    }
    else
    {
      caret = replace(dropPos, dropPos, GetGlobalTextWide((HGLOBAL) wParam));
      selStart = dropPos;
      return DROPEFFECT_COPY;
    }
    return lParam;
  case WM_SYSKEYDOWN:
  case WM_KEYDOWN:
    onKey(wParam);
    return 0;
  case WM_COMMAND:
    switch (LOWORD(wParam))
    {
    case ID_EDIT_UNDO:
      {
        bool glue = true;
        bool first = true;
        while (glue && historyPos > 0)
        {
          HistoryItem& h = history[--historyPos];
          replace(h.begin, h.end, h.text, &h);
          glue = h.glue;
          h.glue = !first;
          first = false;
        }
      }
      break;
    case ID_EDIT_REDO:
      {
        bool glue = true;
        bool first = true;
        while (glue && historyPos < history.length())
        {
          HistoryItem& h = history[historyPos++];
          replace(h.begin, h.end, h.text, &h);
          glue = h.glue;
          h.glue = !first;
          first = false;
        }
      }
      break;
    case ID_EDIT_SELECTALL:
      selStart = 0;
      caret = getTextLength();
      updateCaret();
      break;
    case ID_EDIT_COPY:
      if (caret != selStart)
        SetClipboard(CF_UNICODETEXT, CreateGlobalText(getSelection()));
      else
      {
        POINT pt = toPoint(caret);
        pt.x = 0;
        int start = fromPoint(pt);
        if (pt.y < lines.length() - 1)
          pt.y++;
        else
          pt.x = lines[pt.y].text.length();
        int end = fromPoint(pt);
        if (pCopyLine)
          pCopyLine->Release();
        pCopyLine = SetClipboard(CF_UNICODETEXT, CreateGlobalText(substring(start, end)));
        if (pCopyLine)
          pCopyLine->AddRef();
      }
      break;
    case ID_EDIT_CUT:
      if (caret != selStart)
      {
        SetClipboard(CF_UNICODETEXT, CreateGlobalText(getSelection()));
        replace(selStart, caret, L"");
      }
      else
      {
        POINT pt = toPoint(caret);
        POINT save = pt;
        pt.x = 0;
        int start = fromPoint(pt);
        if (pt.y < lines.length() - 1)
          pt.y++;
        else
          pt.x = lines[pt.y].text.length();
        int end = fromPoint(pt);
        if (pCopyLine)
          pCopyLine->Release();
        pCopyLine = SetClipboard(CF_UNICODETEXT, CreateGlobalText(substring(start, end)));
        if (pCopyLine)
          pCopyLine->AddRef();
        replace(start, end, L"");
        caret = selStart = fromPoint(save);
        updateCaret();
      }
      break;
    case ID_EDIT_PASTE:
      {
        ClipboardReader reader(CF_UNICODETEXT);
        if (reader.getData())
        {
          if (OleIsCurrentClipboard(pCopyLine) == S_OK)
          {
            POINT pt = toPoint(caret);
            pt.x = 0;
            caret = selStart = fromPoint(pt);
          }
          selStart = caret = replace(selStart, caret, GetGlobalTextWide(reader.getData()));
          updateCaret();
        }
      }
      break;
    case ID_DEBUG_BREAKPOINT:
      {
        POINT pt = toPoint(caret);
        toggleBreakpoint(pt.y);
      }
      break;
    default:
      return M_UNHANDLED;
    }
    return 0;
  }
  return M_UNHANDLED;
}