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

📄 text.c

📁 在ADS环境下MiniGUI的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
** $Id: text.c,v 1.48 2004/10/06 00:39:04 snig Exp $
**
** The Text Support of GDI.
**
** Copyright (C) 2000 ~ 2002 Wei Yongming.
** Copyright (C) 2003 Feynman Software.
**
** Current maintainer: Wei Yongming.
**
** Create date: 2000.4.19
*/

/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

/*
** TODO:
*/ 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "common.h"
#include "minigui.h"
#include "gdi.h"
#include "window.h"
#include "cliprect.h"
#include "gal.h"
#include "internals.h"
#include "ctrlclass.h"
#include "dc.h"
#include "drawtext.h"
#include "cursor.h"

extern BOOL dc_GenerateECRgn (PDC pdc, BOOL fForce);

int GUIAPI GetFontHeight (HDC hdc)
{
    PDC pdc = dc_HDC2PDC(hdc);

    return pdc->pLogFont->size;
}

int GUIAPI GetMaxFontWidth (HDC hdc)
{
    PDC pdc = dc_HDC2PDC(hdc);
    DEVFONT* sbc_devfont = pdc->pLogFont->sbc_devfont;
    DEVFONT* mbc_devfont = pdc->pLogFont->mbc_devfont;
    int sbc_max_width = (*sbc_devfont->font_ops->get_max_width) (pdc->pLogFont, sbc_devfont);
    int mbc_max_width = 0;

    if (mbc_devfont)
        mbc_max_width = (*mbc_devfont->font_ops->get_max_width) (pdc->pLogFont, mbc_devfont);
    
    return (sbc_max_width > mbc_max_width) ? sbc_max_width : mbc_max_width;
}

void GUIAPI GetTextExtent (HDC hdc, const char* spText, int len, SIZE* pSize)
{
    PDC pdc;

    pdc = dc_HDC2PDC(hdc);
    if (len < 0) len = strlen (spText);

    gdi_get_TextOut_extent (pdc, pdc->pLogFont, spText, len, pSize);
}

void GUIAPI GetTabbedTextExtent (HDC hdc, const char* spText, int len, SIZE* pSize)
{
    PDC pdc;

    pdc = dc_HDC2PDC(hdc);
    if (len < 0) len = strlen (spText);

    gdi_get_TabbedTextOut_extent (pdc, pdc->pLogFont, pdc->tabstop, 
                spText, len, pSize, NULL);
}

void GUIAPI GetLastTextOutPos (HDC hdc, POINT* pt)
{
    PDC pdc;

    pdc = dc_HDC2PDC(hdc);
    *pt = pdc->CurTextPos;
}

int GUIAPI TextOutLen (HDC hdc, int x, int y, const char* spText, int len)
{
    PCLIPRECT pClipRect;
    PDC pdc;
    RECT rcOutput;
    SIZE size;

    if (!spText || len == 0) return 0;
    if (len < 0) len = strlen (spText);

    pdc = dc_HDC2PDC(hdc);

    gdi_get_TextOut_extent (pdc, pdc->pLogFont, spText, len, &size);
    {
        // update text out position
        int width = size.cx;

        extent_x_SP2LP (pdc, &width);
        pdc->CurTextPos.x = x + width;
        pdc->CurTextPos.y = y;
    }

    if (dc_IsGeneralHDC(hdc)) {
        pthread_mutex_lock (&pdc->pGCRInfo->lock);
        if (!dc_GenerateECRgn (pdc, FALSE)) {
            pthread_mutex_unlock (&pdc->pGCRInfo->lock);
            return size.cx;
        }
    }

    // Transfer logical to device to screen here.
    coor_LP2SP(pdc, &x, &y);

    rcOutput.left = x;
    rcOutput.top  = y;
    rcOutput.right = x + size.cx + 1;
    rcOutput.bottom = y + size.cy + 1;
    NormalizeRect(&rcOutput);

    pthread_mutex_lock (&__mg_gdilock);
    IntersectRect (&rcOutput, &rcOutput, &pdc->ecrgn.rcBound);
    if( !dc_IsMemHDC(hdc) ) ShowCursorForGDI(FALSE, &rcOutput);

    // set graphics context.
    GAL_SetGC(pdc->gc);

    // set text out mode.
    pClipRect = pdc->ecrgn.head;
    while(pClipRect)
    {
        if (DoesIntersect (&rcOutput, &pClipRect->rc)) {
            GAL_SetClipping(pdc->gc, pClipRect->rc.left, pClipRect->rc.top,
                    pClipRect->rc.right - 1, pClipRect->rc.bottom - 1);

            gdi_strnwrite (pdc, x, y, spText, len);
        }
            
        pClipRect = pClipRect->next;
    }

    if( !dc_IsMemHDC(hdc) ) ShowCursorForGDI(TRUE, &rcOutput);
    pthread_mutex_unlock(&__mg_gdilock);
    if (dc_IsGeneralHDC(hdc)) pthread_mutex_unlock (&pdc->pGCRInfo->lock);

    return size.cx;
}

int GUIAPI TabbedTextOutLen (HDC hdc, int x, int y, const char* spText, int len) 
{
    PCLIPRECT pClipRect;
    PDC pdc;
    SIZE size;
    RECT rcOutput;

    if (len == 0) return 0;
    if (len < 0) len = strlen (spText);

    pdc = dc_HDC2PDC(hdc);

    coor_LP2SP (pdc, &pdc->CurTextPos.x, &pdc->CurTextPos.y);
    gdi_get_TabbedTextOut_extent (pdc, pdc->pLogFont, pdc->tabstop, spText, len, 
                &size, &pdc->CurTextPos);
    coor_SP2LP (pdc, &pdc->CurTextPos.x, &pdc->CurTextPos.y);

    if (dc_IsGeneralHDC(hdc)) {
        pthread_mutex_lock (&pdc->pGCRInfo->lock);
        if (!dc_GenerateECRgn (pdc, FALSE)) {
            pthread_mutex_unlock (&pdc->pGCRInfo->lock);
            return size.cx;
        }
    }

    // Transfer logical to device to screen here.
    coor_LP2SP(pdc, &x, &y);
    
    rcOutput.left = x;
    rcOutput.top  = y;
    rcOutput.right = x + size.cx + 1;
    rcOutput.bottom = y + size.cy + 1;
    NormalizeRect(&rcOutput);

    pthread_mutex_lock (&__mg_gdilock);
    IntersectRect (&rcOutput, &rcOutput, &pdc->ecrgn.rcBound);
    if( !dc_IsMemHDC(hdc) ) ShowCursorForGDI(FALSE, &rcOutput);

    // set graphics context.
    GAL_SetGC(pdc->gc);

    pClipRect = pdc->ecrgn.head;
    while(pClipRect)
    {
        if (DoesIntersect (&rcOutput, &pClipRect->rc)) {
            GAL_SetClipping(pdc->gc, pClipRect->rc.left, pClipRect->rc.top,
                    pClipRect->rc.right - 1, pClipRect->rc.bottom - 1);

            gdi_tabbedtextout (pdc, x, y, spText, len);
        }
            
        pClipRect = pClipRect->next;
    }

    if( !dc_IsMemHDC(hdc) ) ShowCursorForGDI(TRUE, &rcOutput);
    pthread_mutex_unlock(&__mg_gdilock);
    if (dc_IsGeneralHDC(hdc)) pthread_mutex_unlock (&pdc->pGCRInfo->lock);

    return size.cx;
}

int GUIAPI TabbedTextOutEx (HDC hdc, int x, int y, const char* spText,
		int nCount, int nTabs, int *pTabPos, int nTabOrig)
{
    PDC pdc;
    int line_len, sub_len;
    int nr_tab = 0, tab_pos, def_tab;
    int x_orig = x, max_x = x;
    int line_height;
    int nr_delim_newline, nr_delim_tab;

    if (nCount == 0) return 0;
    if (nCount < 0) nCount = strlen (spText);

    pdc = dc_HDC2PDC(hdc);

    line_height = pdc->pLogFont->size + pdc->alExtra + pdc->blExtra;
    y += pdc->alExtra;
    if (nTabs == 0 || pTabPos == NULL) {
        int ave_width = (*pdc->pLogFont->sbc_devfont->font_ops->get_ave_width)
                        (pdc->pLogFont, pdc->pLogFont->sbc_devfont);
        def_tab = ave_width * pdc->tabstop;
    }
    else
        def_tab = pTabPos [nTabs - 1];

    while (nCount) {
        line_len = substrlen (spText, nCount, '\n', &nr_delim_newline);

        nCount -= line_len + nr_delim_newline;

        nr_tab = 0;
        x = x_orig;
        tab_pos = nTabOrig;
        while (line_len) {
            int i, width;

            sub_len = substrlen (spText, line_len, '\t', &nr_delim_tab);

            width = TextOutLen (hdc, x, y, spText, sub_len);

            x += width; 
            if (x >= tab_pos) {
                while (x >= tab_pos)
                    tab_pos += (nr_tab >= nTabs) ? def_tab : pTabPos [nr_tab++];
                for (i = 0; i < nr_delim_tab - 1; i ++)
                    tab_pos += (nr_tab >= nTabs) ? def_tab : pTabPos [nr_tab++];
            }
            else {
                for (i = 0; i < nr_delim_tab; i ++)
                    tab_pos += (nr_tab >= nTabs) ? def_tab : pTabPos [nr_tab++];
            }

            x = tab_pos;

            line_len -= sub_len + nr_delim_tab;
            spText += sub_len + nr_delim_tab;
        }

        if (max_x < x) max_x = x;

        spText += nr_delim_newline;
        y += line_height * nr_delim_newline;
    }

    return max_x - x_orig;
}

static void txtDrawOneLine (PDC pdc, const char* pText, int nLen, int x, int y,
                    const RECT* prcOutput, UINT nFormat, int nTabWidth)
{
    RECT rcInter;
    PCLIPRECT pClipRect;

    pClipRect = pdc->ecrgn.head;
    while(pClipRect)
    {
        if (IntersectRect (&rcInter, prcOutput, &pClipRect->rc)) {
            GAL_SetClipping(pdc->gc, rcInter.left, rcInter.top,
                    rcInter.right - 1, rcInter.bottom - 1);

            if (nFormat & DT_EXPANDTABS) {
                const char* sub = pText;
                const char* left;
                int nSubLen = nLen;
                int nOutputLen;
                
                while ((left = strnchr (sub, nSubLen, '\t'))) {
                    
                    nOutputLen = left - sub;
                    x += gdi_strnwrite (pdc, x, y, sub, nOutputLen);
                    
                    nSubLen -= (nOutputLen + 1);
                    sub = left + 1;
                    x += nTabWidth;
                }

                if (nSubLen != 0)
                    gdi_strnwrite (pdc, x, y, sub, nSubLen);
            }
            else
                gdi_strnwrite (pdc, x, y, pText, nLen);
        }
            
        pClipRect = pClipRect->next;
    }
}

static int txtGetWidthOfNextWord (PDC pdc, const char* pText, int nCount, int* nChars)
{
    int width, extra;
    DEVFONT* sbc_devfont = pdc->pLogFont->sbc_devfont;
    DEVFONT* mbc_devfont = pdc->pLogFont->mbc_devfont;
    WORDINFO word_info; 

    *nChars = 0;
    if (nCount == 0) return 0;

    extra = pdc->cExtra;
    if (mbc_devfont) {
        int mbc_pos, sub_len;

        mbc_pos = (*mbc_devfont->charset_ops->pos_first_char) (pText, nCount);
        if (mbc_pos == 0) {
            sub_len = (*mbc_devfont->charset_ops->len_first_substr) (pText, nCount);

            (*mbc_devfont->charset_ops->get_next_word) (pText, sub_len, &word_info);
            if (pdc->pLogFont->style & FS_WEIGHT_BOLD 
                    && !(mbc_devfont->style & FS_WEIGHT_BOLD))
                extra ++;
            width = (*mbc_devfont->font_ops->get_str_width) 
                        (pdc->pLogFont, mbc_devfont, pText, word_info.len, extra);

            *nChars = word_info.len;
            return width;
        }
        else if (mbc_pos > 0)
            nCount = mbc_pos;
    }

    (*sbc_devfont->charset_ops->get_next_word) (pText, nCount, &word_info);
    if (pdc->pLogFont->style & FS_WEIGHT_BOLD 
            && !(sbc_devfont->style & FS_WEIGHT_BOLD))
        extra ++;
    width = (*sbc_devfont->font_ops->get_str_width) 
                    (pdc->pLogFont, sbc_devfont, pText, word_info.len, extra);
    *nChars = word_info.len;

    return width;
}

/*
** This function return the normal characters' number (refrence)
** and output width of the line (return value).
*/
static int txtGetOneLine (PDC pdc, const char* pText, int nCount, int nTabWidth, 
                int maxwidth, UINT uFormat, int* nChar)
{
    int x = 0, y = 0;
    int wordLen;
    int wordWidth;
    int lineWidth;

    if (uFormat & DT_SINGLELINE) {
        SIZE size;

        if (uFormat & DT_EXPANDTABS)
            gdi_get_TabbedTextOut_extent (pdc, pdc->pLogFont, pdc->tabstop, 
                pText, nCount, &size, NULL);
        else
            gdi_get_TextOut_extent (pdc, pdc->pLogFont, pText, nCount, &size);

        *nChar = nCount;
        return size.cx;
    }

    *nChar = 0;
    lineWidth = 0;
    while (TRUE) {
        wordWidth = txtGetWidthOfNextWord (pdc, pText, nCount, &wordLen);

        if (uFormat & DT_WORDBREAK) {
            if (wordWidth > maxwidth) {
                SIZE size;

                wordLen = GetTextExtentPoint ((HDC)pdc, pText, nCount, 
                            maxwidth - lineWidth, NULL, NULL, NULL, &size);

                if (wordLen == 0) {
                    wordLen = GetFirstMCharLen (GetCurFont ((HDC)pdc), pText, nCount);
                    gdi_get_TextOut_extent (pdc, pdc->pLogFont, pText, wordLen, &size);
                    wordWidth = size.cx;
                }

                *nChar += wordLen;
                lineWidth += wordWidth;
                break;
            }
            else if (lineWidth + wordWidth > maxwidth)
                break;
        }

        pText += wordLen;
        nCount -= wordLen;
        lineWidth += wordWidth;
        *nChar += wordLen;

        if (nCount == 0)
            break;

        if (*pText == '\t') {
            (*nChar)++;
            if (uFormat & DT_EXPANDTABS) {
                lineWidth += nTabWidth;
                gdi_start_new_line (pdc->pLogFont);
            }
            else
                lineWidth += gdi_width_one_char 
                        (pdc->pLogFont, pdc->pLogFont->sbc_devfont, pText, 1, &x, &y);
            pText ++;
            nCount --;
        }
        else if (*pText == '\n' || *pText == '\r') {
            (*nChar) ++;
            break;
        }
        else if (*pText == ' ') {
            lineWidth += gdi_width_one_char
                        (pdc->pLogFont, pdc->pLogFont->sbc_devfont, pText, 1, &x, &y);
            (*nChar) ++;
            pText ++;
            nCount --;
        }
    }
    
    return lineWidth;
}

int DrawTextEx2 (HDC hdc, const char* pText, int nCount, 
                RECT* pRect, int indent, UINT nFormat, DTFIRSTLINE *firstline)
{

⌨️ 快捷键说明

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