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

📄 wrap.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
      /* wc->pt.x += run->nWidth; */
      /* skip runs consisting of only whitespaces */
      return p->next;
    }

    if (run->nFlags & MERF_STARTWHITE) {
      /* try to split the run at the first non-white char */
      int black;
      black = ME_FindNonWhitespaceV(run->strText, 0);
      if (black) {
        wc->bOverflown = FALSE;
        pp = ME_SplitRun(wc->context, p, black);
        p->member.run.nFlags |= MERF_SKIPPED;
        ME_InsertRowStart(wc, pp);
        return pp;
      }
    }
    /* black run: the row goes from pRowStart to the previous run */
    ME_InsertRowStart(wc, p);
    return p;
  }
  /* we're not at the end of the row */
  /* will current run fit? */
  if (wc->pt.x + run->nWidth > wc->nAvailWidth)
  {
    int loc = wc->nAvailWidth - wc->pt.x;
    /* total white run ? */
    if (run->nFlags & MERF_WHITESPACE) {
      /* let the overflow logic handle it */
      wc->bOverflown = TRUE;
      return p;
    }
    /* graphics or TAB - we can split before */
    if (run->nFlags & (MERF_GRAPHICS|MERF_TAB)) {
      wc->bOverflown = TRUE;
      return p;
    }
    /* can we separate out the last spaces ? (to use overflow logic later) */
    if (run->nFlags & MERF_ENDWHITE)
    {
      /* we aren't sure if it's *really* necessary, it's a good start however */
      int black = ME_ReverseFindNonWhitespaceV(run->strText, len);
      ME_SplitRun(wc->context, p, black);
      /* handle both parts again */
      return p;
    }
    /* determine the split point by backtracking */
    pp = ME_SplitByBacktracking(wc, p, loc);
    if (pp == wc->pRowStart)
    {
      /* we had only spaces so far, entire content can be omitted */
      wc->pt.x = 0;
      return p->next;
    }
    if (p != pp) /* found a suitable split point */
    {
      wc->bOverflown = TRUE;
      return pp;
    }
    /* we detected that it's best to split on start of this run */
    if (wc->bOverflown)
      return pp;
    ERR("failure!\n");
    /* not found anything - writing over margins is the only option left */
  }
  if ((run->nFlags & (MERF_SPLITTABLE | MERF_STARTWHITE))
    || ((run->nFlags & (MERF_GRAPHICS|MERF_TAB)) && (p != wc->pRowStart)))
  {
    wc->pLastSplittableRun = p;
    wc->ptLastSplittableRun = wc->pt;
  }
  wc->pt.x += run->nWidth;
  return p->next;
}

void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) {
  ME_DisplayItem *p;
  ME_WrapContext wc;
  int dpi = GetDeviceCaps(c->hDC, LOGPIXELSX);

  assert(tp->type == diParagraph);
  if (!(tp->member.para.nFlags & MEPF_REWRAP)) {
    return;
  }
  ME_PrepareParagraphForWrapping(c, tp);

  wc.context = c;
/*   wc.para_style = tp->member.para.style; */
  wc.style = NULL;
  tp->member.para.nRightMargin = tp->member.para.pFmt->dxRightIndent*dpi/1440;
  tp->member.para.nFirstMargin = tp->member.para.pFmt->dxStartIndent*dpi/1440;
  tp->member.para.nLeftMargin = (tp->member.para.pFmt->dxStartIndent+tp->member.para.pFmt->dxOffset)*dpi/1440;
  wc.nFirstMargin = tp->member.para.nFirstMargin;
  wc.nLeftMargin = tp->member.para.nLeftMargin;
  wc.nRightMargin = tp->member.para.nRightMargin;
  wc.nRow = 0;
  wc.pt.x = 0;
  wc.pt.y = 0;
  wc.nTotalWidth = c->rcView.right - c->rcView.left;
  wc.nAvailWidth = wc.nTotalWidth - wc.nFirstMargin - wc.nRightMargin;
  wc.pRowStart = NULL;

  ME_BeginRow(&wc);
  for (p = tp->next; p!=tp->member.para.next_para; ) {
    assert(p->type != diStartRow);
    if (p->type == diRun) {
      p = ME_WrapHandleRun(&wc, p);
      continue;
    }
    p = p->next;
  }
  ME_WrapEndParagraph(&wc, p);
  tp->member.para.nFlags &= ~MEPF_REWRAP;
  tp->member.para.nHeight = wc.pt.y;
  tp->member.para.nRows = wc.nRow;
}


void ME_PrepareParagraphForWrapping(ME_Context *c, ME_DisplayItem *tp) {
  ME_DisplayItem *p, *pRow;

  /* remove all items that will be reinserted by paragraph wrapper anyway */
  tp->member.para.nRows = 0;
  for (p = tp->next; p!=tp->member.para.next_para; p = p->next) {
    switch(p->type) {
      case diStartRow:
        pRow = p;
        p = p->prev;
        ME_Remove(pRow);
        ME_DestroyDisplayItem(pRow);
        break;
      default:
        break;
    }
  }
  /* join runs that can be joined, set up flags */
  for (p = tp->next; p!=tp->member.para.next_para; p = p->next) {
    int changed = 0;
    switch(p->type) {
      case diStartRow: assert(0); break; /* should have deleted it */
      case diRun:
        while (p->next->type == diRun) { /* FIXME */
          if (ME_CanJoinRuns(&p->member.run, &p->next->member.run)) {
            ME_JoinRuns(c->editor, p);
            changed = 1;
          }
          else
            break;
        }
        p->member.run.nFlags &= ~MERF_CALCBYWRAP;
        break;
      default:
        break;
    }
  }
}

BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) {
  HWND hWnd = editor->hWnd;
  HDC hDC = GetDC(hWnd);
  ME_DisplayItem *item;
  ME_Context c;
  BOOL bModified = FALSE;
  int yStart = -1, yEnd = -1;

  ME_InitContext(&c, editor, hDC);
  c.pt.x = 0;
  c.pt.y = 0;
  item = editor->pBuffer->pFirst->next;
  while(item != editor->pBuffer->pLast) {
    BOOL bRedraw = FALSE;

    assert(item->type == diParagraph);
    if ((item->member.para.nFlags & MEPF_REWRAP)
     || (item->member.para.nYPos != c.pt.y))
      bRedraw = TRUE;
    item->member.para.nYPos = c.pt.y;

    ME_WrapTextParagraph(&c, item);

    if (bRedraw)
    {
      item->member.para.nFlags |= MEPF_REPAINT;
      if (yStart == -1)
        yStart = c.pt.y;
    }

    bModified = bModified | bRedraw;

    c.pt.y += item->member.para.nHeight;
    if (bRedraw)
      yEnd = c.pt.y;
    item = item->member.para.next_para;
  }
  editor->sizeWindow.cx = c.rcView.right-c.rcView.left;
  editor->sizeWindow.cy = c.rcView.bottom-c.rcView.top;
  
  editor->nTotalLength = c.pt.y;

  ME_DestroyContext(&c);
  ReleaseDC(hWnd, hDC);
  
  if (bModified || editor->nTotalLength < editor->nLastTotalLength)
    ME_InvalidateMarkedParagraphs(editor);
  return bModified;
}

void ME_InvalidateMarkedParagraphs(ME_TextEditor *editor) {
  ME_Context c;
  HDC hDC = GetDC(editor->hWnd);

  ME_InitContext(&c, editor, hDC);
  if (editor->bRedraw)
  {
    RECT rc = c.rcView;
    int ofs = ME_GetYScrollPos(editor); 
     
    ME_DisplayItem *item = editor->pBuffer->pFirst;
    while(item != editor->pBuffer->pLast) {
      if (item->member.para.nFlags & MEPF_REPAINT) { 
        rc.top = item->member.para.nYPos - ofs;
        rc.bottom = item->member.para.nYPos + item->member.para.nHeight - ofs;
        InvalidateRect(editor->hWnd, &rc, TRUE);
      }
      item = item->member.para.next_para;
    }
    if (editor->nTotalLength < editor->nLastTotalLength)
    {
      rc.top = editor->nTotalLength - ofs;
      rc.bottom = editor->nLastTotalLength - ofs;
      InvalidateRect(editor->hWnd, &rc, TRUE);
    }
  }
  ME_DestroyContext(&c);
  ReleaseDC(editor->hWnd, hDC);
}


void
ME_SendRequestResize(ME_TextEditor *editor, BOOL force)
{
  if (editor->nEventMask & ENM_REQUESTRESIZE)
  {
    RECT rc;

    GetClientRect(editor->hWnd, &rc);

    if (force || rc.bottom != editor->nTotalLength)
    {
      REQRESIZE info;

      info.nmhdr.hwndFrom = editor->hWnd;
      info.nmhdr.idFrom = GetWindowLongW(editor->hWnd, GWLP_ID);
      info.nmhdr.code = EN_REQUESTRESIZE;
      info.rc = rc;
      info.rc.bottom = editor->nTotalLength;
    
      SendMessageW(GetParent(editor->hWnd), WM_NOTIFY,
                   info.nmhdr.idFrom, (LPARAM)&info);
    }
  }
}

⌨️ 快捷键说明

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