⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 editor.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
    int count = 0;
    int ystart, yend;
    while(p) {
      p = ME_FindItemFwd(p, diStartRowOrParagraphOrEnd);
      if (p->type == diTextEnd)
        break;
      if (p->type == diParagraph) {
        ypara = p->member.para.nYPos;
        continue;
      }
      ystart = ypara + p->member.row.nYPos;
      yend = ystart + p->member.row.nHeight;
      if (y < yend) {
        break;
      }
      count++;
    }
    return count;
  }
  case EM_HIDESELECTION:
  {
     editor->bHideSelection = (wParam != 0);
     ME_InvalidateSelection(editor);
     return 0;
  }
  case EM_LINESCROLL:
  {
    ME_ScrollDown(editor, lParam * 8); /* FIXME follow the original */
    return TRUE; /* Should return false if a single line richedit control */
  }
  case WM_CLEAR:
  {
    int from, to;
    ME_GetSelection(editor, &from, &to);
    ME_InternalDeleteText(editor, from, to-from);
    ME_CommitUndo(editor);
    ME_UpdateRepaint(editor);
    return 0;
  }
  case EM_REPLACESEL:
  {
    int from, to;
    ME_Style *style;
    LPWSTR wszText = ME_ToUnicode(unicode, (void *)lParam);
    size_t len = lstrlenW(wszText);
    TRACE("EM_REPLACESEL - %s\n", debugstr_w(wszText));

    ME_GetSelection(editor, &from, &to);
    style = ME_GetSelectionInsertStyle(editor);
    ME_InternalDeleteText(editor, from, to-from);
    ME_InsertTextFromCursor(editor, 0, wszText, len, style);
    ME_ReleaseStyle(style);
    /* drop temporary style if line end */
    /*
     * FIXME question: does abc\n mean: put abc,
     * clear temp style, put \n? (would require a change)
     */
    if (len>0 && wszText[len-1] == '\n')
      ME_ClearTempStyle(editor);
    ME_EndToUnicode(unicode, wszText);
    ME_CommitUndo(editor);
    if (!wParam)
      ME_EmptyUndoStack(editor);
    ME_UpdateRepaint(editor);
    return 0;
  }
  case EM_SCROLLCARET:
  {
    int top, bottom; /* row's edges relative to document top */
    int nPos;
    ME_DisplayItem *para, *row;
    
    nPos = ME_GetYScrollPos(editor);
    row = ME_RowStart(editor->pCursors[0].pRun);
    para = ME_GetParagraph(row);
    top = para->member.para.nYPos + row->member.row.nYPos;
    bottom = top + row->member.row.nHeight;
    
    if (top < nPos) /* caret above window */
      ME_ScrollAbs(editor,  top);
    else if (nPos + editor->sizeWindow.cy < bottom) /*below*/
      ME_ScrollAbs(editor, bottom - editor->sizeWindow.cy);
    return 0;
  }
  case WM_SETFONT:
  {
    LOGFONTW lf;
    CHARFORMAT2W fmt;
    HDC hDC;
    BOOL bRepaint = LOWORD(lParam);
    
    if (!wParam)
      wParam = (WPARAM)GetStockObject(SYSTEM_FONT); 
    GetObjectW((HGDIOBJ)wParam, sizeof(LOGFONTW), &lf);
    hDC = GetDC(hWnd);
    ME_CharFormatFromLogFont(hDC, &lf, &fmt); 
    ReleaseDC(hWnd, hDC);   
    ME_SetCharFormat(editor, 0, ME_GetTextLength(editor), &fmt);
    ME_SetDefaultCharFormat(editor, &fmt);

    ME_CommitUndo(editor);
    if (bRepaint)
      ME_RewrapRepaint(editor);
    return 0;
  }
  case WM_SETTEXT:
  {
    ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor));
    if (lParam)
    {
      TRACE("WM_SETTEXT lParam==%lx\n",lParam);
      if (!unicode && !strncmp((char *)lParam, "{\\rtf", 5))
      {
        /* Undocumented: WM_SETTEXT supports RTF text */
        ME_StreamInRTFString(editor, 0, (char *)lParam);
      }
      else
      {
        LPWSTR wszText = ME_ToUnicode(unicode, (void *)lParam);
        TRACE("WM_SETTEXT - %s\n", debugstr_w(wszText)); /* debugstr_w() */
        if (lstrlenW(wszText) > 0)
        {
          /* uses default style! */
          ME_InsertTextFromCursor(editor, 0, wszText, -1, editor->pBuffer->pDefaultStyle);
        }
        ME_EndToUnicode(unicode, wszText);
      }
    }
    else
      TRACE("WM_SETTEXT - NULL\n");
    ME_CommitUndo(editor);
    ME_EmptyUndoStack(editor);
    ME_SetSelection(editor, 0, 0);
    ME_UpdateRepaint(editor);
    return 1;
  }
  case EM_CANPASTE:
  {
    UINT nRTFFormat = RegisterClipboardFormatA("Rich Text Format");
    if (IsClipboardFormatAvailable(nRTFFormat))
      return TRUE;
    if (IsClipboardFormatAvailable(CF_UNICODETEXT))
      return TRUE;
    return FALSE;
  }
  case WM_PASTE:
  {    
    DWORD dwFormat = 0;
    EDITSTREAM es;
    ME_GlobalDestStruct gds;
    UINT nRTFFormat = RegisterClipboardFormatA("Rich Text Format");
    UINT cf = 0;

    if (IsClipboardFormatAvailable(nRTFFormat))
      cf = nRTFFormat, dwFormat = SF_RTF;
    else if (IsClipboardFormatAvailable(CF_UNICODETEXT))
      cf = CF_UNICODETEXT, dwFormat = SF_TEXT|SF_UNICODE;
    else
      return 0;

    if (!OpenClipboard(hWnd))
      return 0;
    gds.hData = GetClipboardData(cf);
    gds.nLength = 0;
    es.dwCookie = (DWORD)&gds;
    es.pfnCallback = dwFormat == SF_RTF ? ME_ReadFromHGLOBALRTF : ME_ReadFromHGLOBALUnicode;
    ME_StreamIn(editor, dwFormat|SFF_SELECTION, &es);

    CloseClipboard();
    return 0;
  }
  case WM_CUT:
  case WM_COPY:
  {
    LPDATAOBJECT dataObj = NULL;
    CHARRANGE range;
    HRESULT hr = S_OK;
    
    if (editor->cPasswordMask)
      return 0; /* Copying or Cutting masked text isn't allowed */
    
    ME_GetSelection(editor, (int*)&range.cpMin, (int*)&range.cpMax);
    if(editor->lpOleCallback)
        hr = IRichEditOleCallback_GetClipboardData(editor->lpOleCallback, &range, RECO_COPY, &dataObj);
    if(FAILED(hr) || !dataObj)
        hr = ME_GetDataObject(editor, &range, &dataObj);
    if(SUCCEEDED(hr)) {
        hr = OleSetClipboard(dataObj);
        IDataObject_Release(dataObj);
    }
    if (SUCCEEDED(hr) && msg == WM_CUT)
    {
      ME_InternalDeleteText(editor, range.cpMin, range.cpMax-range.cpMin);
      ME_CommitUndo(editor);
      ME_UpdateRepaint(editor);
    }
    return 0;
  }
  case WM_GETTEXTLENGTH:
    return ME_GetTextLength(editor);
  case EM_GETTEXTLENGTHEX:
    return ME_GetTextLengthEx(editor, (GETTEXTLENGTHEX *)wParam);
  case WM_GETTEXT:
  {
    TEXTRANGEW tr; /* W and A differ only by rng->lpstrText */
    tr.chrg.cpMin = 0;
    tr.chrg.cpMax = wParam ? (wParam - 1) : 0;
    tr.lpstrText = (WCHAR *)lParam;
    return RichEditWndProc_common(hWnd, EM_GETTEXTRANGE, 0, (LPARAM)&tr, unicode);
  }
  case EM_GETTEXTEX:
  {
    GETTEXTEX *ex = (GETTEXTEX*)wParam;
    int nStart, nCount;

    if (ex->flags & ~(GT_SELECTION | GT_USECRLF))
      FIXME("GETTEXTEX flags 0x%08x not supported\n", ex->flags & ~(GT_SELECTION | GT_USECRLF));

    if (ex->flags & GT_SELECTION)
    {
      ME_GetSelection(editor, &nStart, &nCount);
      nCount -= nStart;
      nCount = min(nCount, ex->cb - 1);
    }
    else
    {
      nStart = 0;
      nCount = ex->cb - 1;
    }
    if (ex->codepage == 1200)
    {
      nCount = min(nCount, ex->cb / sizeof(WCHAR) - 1);
      return ME_GetTextW(editor, (LPWSTR)lParam, nStart, nCount, ex->flags & GT_USECRLF);
    }
    else
    {
      /* potentially each char may be a CR, why calculate the exact value with O(N) when
        we can just take a bigger buffer? :) */
      int crlfmul = (ex->flags & GT_USECRLF) ? 2 : 1;
      LPWSTR buffer = richedit_alloc((crlfmul*nCount + 1) * sizeof(WCHAR));
      DWORD buflen = ex->cb;
      LRESULT rc;
      DWORD flags = 0;

      buflen = ME_GetTextW(editor, buffer, nStart, nCount, ex->flags & GT_USECRLF);
      rc = WideCharToMultiByte(ex->codepage, flags, buffer, -1, (LPSTR)lParam, ex->cb, ex->lpDefaultChar, ex->lpUsedDefaultChar);
      if (rc) rc--; /* do not count 0 terminator */

      richedit_free(buffer);
      return rc;
    }
  }
  case EM_GETSELTEXT:
  {
    int from, to;
    TEXTRANGEW tr; /* W and A differ only by rng->lpstrText */
    ME_GetSelection(editor, &from, &to);
    tr.chrg.cpMin = from;
    tr.chrg.cpMax = to;
    tr.lpstrText = (WCHAR *)lParam;
    return RichEditWndProc_common(hWnd, EM_GETTEXTRANGE, 0, (LPARAM)&tr, unicode);
  }
  case EM_GETSCROLLPOS:
  {
      POINT *point = (POINT *)lParam;
      point->x = 0; /* FIXME side scrolling not implemented */
      point->y = ME_GetYScrollPos(editor);
      return 1;
  }
  case EM_GETTEXTRANGE:
  {
    TEXTRANGEW *rng = (TEXTRANGEW *)lParam;
    TRACE("EM_GETTEXTRANGE min=%d max=%d unicode=%d emul1.0=%d length=%d\n",
      rng->chrg.cpMin, rng->chrg.cpMax, unicode,
      editor->bEmulateVersion10, ME_GetTextLength(editor));
    if (unicode)
      return ME_GetTextW(editor, rng->lpstrText, rng->chrg.cpMin, rng->chrg.cpMax-rng->chrg.cpMin, editor->bEmulateVersion10);
    else
    {
      int nLen = rng->chrg.cpMax-rng->chrg.cpMin;
      WCHAR *p = ALLOC_N_OBJ(WCHAR, nLen+1);
      int nChars = ME_GetTextW(editor, p, rng->chrg.cpMin, nLen, editor->bEmulateVersion10);
      /* FIXME this is a potential security hole (buffer overrun) 
         if you know more about wchar->mbyte conversion please explain
      */
      WideCharToMultiByte(CP_ACP, 0, p, nChars+1, (char *)rng->lpstrText, nLen+1, NULL, NULL);
      FREE_OBJ(p);
      return nChars;
    }
  }
  case EM_GETLINE:
  {
    ME_DisplayItem *run;
    const unsigned int nMaxChars = *(WORD *) lParam;
    unsigned int nEndChars, nCharsLeft = nMaxChars;
    char *dest = (char *) lParam;
    /* rich text editor 1.0 uses \r\n for line end, 2.0 uses just \r; 
    we need to know how if we have the extra \n or not */
    int nLF = editor->bEmulateVersion10;

    TRACE("EM_GETLINE: row=%d, nMaxChars=%d (%s)\n", (int) wParam, nMaxChars,
          unicode ? "Unicode" : "Ansi");

    run = ME_FindRowWithNumber(editor, wParam);
    if (run == NULL)
      return 0;

    while (nCharsLeft && (run = ME_FindItemFwd(run, diRunOrStartRow))
           && !(run->member.run.nFlags & MERF_ENDPARA))
    {
      unsigned int nCopy;
      ME_String *strText;
      if (run->type != diRun)
        break;
      strText = run->member.run.strText;
      nCopy = min(nCharsLeft, strText->nLen);

      if (unicode)
        lstrcpynW((LPWSTR) dest, strText->szData, nCopy);
      else
        nCopy = WideCharToMultiByte(CP_ACP, 0, strText->szData, nCopy, dest,
                                    nCharsLeft, NULL, NULL);
      dest += nCopy * (unicode ? sizeof(WCHAR) : 1);
      nCharsLeft -= nCopy;
    }

    /* append \r\0 (or \r\n\0 in 1.0), space allowing */
    nEndChars = min(nCharsLeft, 2 + nLF);
    nCharsLeft -= nEndChars;
    if (unicode)
    {
      const WCHAR src[] = {'\r', '\0'};
      const WCHAR src10[] = {'\r', '\n', '\0'};
      lstrcpynW((LPWSTR) dest, nLF ? src10 : src, nEndChars);
    }
    else
      lstrcpynA(dest, nLF ? "\r\n" : "\r", nEndChars);

    TRACE("EM_GETLINE: got %u bytes\n", nMaxChars - nCharsLeft);

    if (nEndChars == 2 + nLF)
      return nMaxChars - nCharsLeft - 1; /* don't count \0 */
    else
      return nMaxChars - nCharsLeft;
  }
  case EM_GETLINECOUNT:
  {
    ME_DisplayItem *item = editor->pBuffer->pFirst->next;
    int nRows = 0;

    while (item != editor->pBuffer->pLast)
    {
      assert(item->type == diParagraph);
      nRows += item->member.para.nRows;
      item = item->member.para.next_para;
    }
    TRACE("EM_GETLINECOUNT: nRows==%d\n", nRows);
    return max(1, nRows);
  }
  case EM_LINEFROMCHAR:
  {
    if (wParam == -1)
      return ME_RowNumberFromCharOfs(editor, ME_GetCursorOfs(editor, 1));
    else
      return ME_RowNumberFromCharOfs(editor, wParam);
  }
  case EM_EXLINEFROMCHAR:
  {
    if (lParam == -1)
      return ME_RowNumberFromCharOfs(editor, ME_GetCursorOfs(editor,1));
    else    
      return ME_RowNumberFromCharOfs(editor, lParam);
  }
  case EM_LINEINDEX:
  {
    ME_DisplayItem *item, *para;
    int nCharOfs;
    
    if (wParam == -1)
      item = ME_FindItemBack(editor->pCursors[0].pRun, diStartRow);
    else
      item = ME_FindRowWithNumber(editor, wParam);
    if (!item)
      return -1;
    para = ME_GetParagraph(item);
    item = ME_FindItemFwd(item, diRun);
    nCharOfs = para->member.para.nCharOfs + item->member.run.nCharOfs;
    TRACE("EM_LINEINDEX: nCharOfs==%d\n", nCharOfs);
    return nCharOfs;
  }
  case EM_LINELENGTH:
  {
    ME_DisplayItem *item, *item_end;
    int nChars = 0, nThisLineOfs = 0, nNextLineOfs = 0;
    
    if (wParam > ME_GetTextLength(editor))
      return 0;
    if (wParam == -1)
    {
      FIXME("EM_LINELENGTH: returning number of unselected characters on lines with selection unsupported.\n");
      return 0;
    }
    item = ME_FindItemAtOffset(editor, diRun, wParam, NULL);
    item = ME_RowStart(item);
    nThisLineOfs = ME_CharOfsFromRunOfs(editor, ME_FindItemFwd(item, diRun), 0);
    item_end = ME_FindItemFwd(item, diStartRowOrParagraphOrEnd);
    if (item_end->type == diStartRow)
      nNextLineOfs = ME_CharOfsFromRunOfs(editor, ME_FindItemFwd(item_end, diRun), 0);
    else
      nNextLineOfs = ME_FindItemFwd(item, diParagraphOrEnd)->member.para.nCharOfs
       - (editor->bEmulateVersion10?2:1);
    nChars = nNextLineOfs - nThisLineOfs;
    TRACE("EM_LINELENGTH(%ld)==%d\n",wParam, nChars);
    return nChars;
  }
  case EM_EXLIMITTEXT:
  {
    if ((int)lParam < 0)
     return 0;
    if (lParam == 0)
      editor->nTextLimit = 65536;
    else
      editor->nTextLimit = (int) lParam;
    return 0;
  }
  case EM_LIMITTEXT:
  {
    if (wParam == 0)
      editor->nTextLimit = 65536;
    else
      editor->nTextLimit = (int) wParam;
    return 0;
  }
  case EM_GETLIMITTEXT:
  {
    return editor->nTextLimit;
  }
  case EM_FINDTEXT:
  {
    FINDTEXTA *ft = (FINDTEXTA *)lParam;
    int nChars = MultiByteToWideChar(CP_ACP, 0, ft->lpstrText, -1, NULL, 0);
    WCHAR *tmp;
    LRESULT r;

    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -