📄 ebmedit.c
字号:
// $Id: ebmedit.c,v 1.5 2005/10/17 07:50:14 tangjb Exp $
//
// medit.c: the Multi-Line Edit Control module.
//
// Copyright (C) 1999, 2000, Chen Lei
// Copyright (C) 1999, 2000, 2001, 2002, Wei Yongming.
//
// Current maintainer: Chen Lei (chenlei@minigui.org).
//
/*
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Library General Public
** License as published by the Free Software Foundation; either
** version 2 of the License, or (at your option) any later version.
**
** This library 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
** Library General Public License for more details.
**
** You should have received a copy of the GNU Library General Public
** License along with this library; if not, write to the Free
** Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
** MA 02111-1307, USA
*/
/*
** Alternatively, the contents of this file may be used under the terms
** of the Mozilla Public License (the "MPL License") in which case the
** provisions of the MPL License are applicable instead of those above.
*/
// Create date: 1999/8/26
//
// Modify records:
//
// Who When Where For What Status
//-----------------------------------------------------------------------------
// WEI Yongming 2000/02/24 Tsinghua Add MPL License Finished
// leon 2000/11/07 BJ Optimize display Finished
// leon 2000/11/07 BJ Fix bugs Finished
// leon 2000/11 BJ Multi-Charset support Finished
// leon 2000/12/28 BJ Fix bug
// M$ like Scrolling Finished
// leon 2001/04/08 BluePoint autowrap support Finished
// TODO:
// * Selection.
// * Undo.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <minigui/common.h>
#include <minigui/minigui.h>
#include <minigui/gdi.h>
#include <minigui/window.h>
#include <minigui/control.h>
#if 0
#include "cliprect.h"
#include "internals.h"
#include "ctrlclass.h"
#endif
#include "ctrlmisc.h"
#include "ebmedit.h"
#include "ebcontrol.h"
#include "ebedit.h"
static int EBMLEditCtrlProc (HWND hWnd, int message, WPARAM wParam, LPARAM lParam);
BOOL RegisterEBMLEditControl (void)
{
// This control class has two names: "medit" and "mledit"
WNDCLASS WndClass;
WndClass.spClassName = "ebmedit";
WndClass.dwStyle = WS_NONE;
WndClass.dwExStyle = WS_EX_NONE;
WndClass.hCursor = GetSystemCursor (IDC_IBEAM);
WndClass.iBkColor = PIXEL_lightwhite;
WndClass.WinProc = EBMLEditCtrlProc;
if (AddNewControlClass (&WndClass) != ERR_OK)
return FALSE;
WndClass.spClassName = "ebmledit";
WndClass.dwStyle = WS_NONE;
WndClass.dwExStyle = WS_EX_NONE;
WndClass.hCursor = GetSystemCursor (IDC_IBEAM);
WndClass.iBkColor = PIXEL_lightwhite;
WndClass.WinProc = EBMLEditCtrlProc;
return AddNewControlClass (&WndClass) == ERR_OK;
}
void EBMLEditControlCleanup (void)
{
// do nothing
UnregisterWindowClass ("ebmedit");
UnregisterWindowClass ("ebmledit");
return;
}
static inline int edtGetOutWidth (HWND hWnd)
{
PEBMLEDITDATA pMLEditData =(PEBMLEDITDATA) GetWindowAdditionalData2(hWnd);
RECT rc;
GetClientRect(hWnd,&rc);
return RECTW(rc) - pMLEditData->leftMargin - pMLEditData->rightMargin;
}
static int edtGetLineNO (const EBMLEDITDATA* pMLEditData, int x)
{
int nline = 0;
if(x>=0)
{
nline = x / pMLEditData->lineHeight;
if (nline <= pMLEditData->linesDisp)
return nline;
}
return -1;
}
int GetRETURNPos(char *str)
{
int i;
for(i=0;i<strlen(str);i++)
{
if(str[i]==10)
return i;
}
return -1;
}
void MLEditEmptyBuffer(PEBMLEDITDATA pMLEditData)
{
PEBLINEDATA temp;
PEBLINEDATA pLineData;
pLineData = pMLEditData->head;
while(pLineData)
{
temp = pLineData->next;
free(pLineData);
pLineData = temp;
}
pMLEditData->head = NULL;
}
// get next wrap line start address according to startPos
// > 0 : next start position
// -1 : end of current line
static int edtGetnextStartPos (HWND hWnd, PEBMLEDITDATA pMLEditData, int startPos)
{
int i = 0;
int outwidth = edtGetOutWidth (hWnd);
if (!pMLEditData->dx_chars)
return -1;
if (pMLEditData->sz.cx - pMLEditData->dx_chars[startPos] <= outwidth)
return -1;
for (i = startPos; i < pMLEditData->fit_chars+1; i++)
{
if (pMLEditData->dx_chars[i]-pMLEditData->dx_chars[startPos] >= outwidth)
return i-1;
}
return -1;
}
static void edtGetLineInfoEx (HWND hWnd, PEBMLEDITDATA pMLEditData, PEBLINEDATA pLineData)
{
HDC hdc = GetClientDC (hWnd);
if (!pMLEditData)
pMLEditData = (PEBMLEDITDATA) GetWindowAdditionalData2(hWnd);
#if 0
if (pMLEditData->logfont)
SelectFont (hdc, pMLEditData->logfont);
#endif
GetTextExtentPoint (hdc,
pLineData->buffer,
pLineData->dataEnd,
GetMaxFontWidth(hdc)*LEN_MLEDIT_BUFFER,//自动换行时,最大的宽度应该为控件的宽度?????
&(pMLEditData->fit_chars),
pMLEditData->pos_chars,
pMLEditData->dx_chars,
&(pMLEditData->sz));
ReleaseDC (hdc);
if (pMLEditData->pos_chars)
pMLEditData->pos_chars[pMLEditData->fit_chars] = pLineData->dataEnd;
if (pMLEditData->dx_chars)
pMLEditData->dx_chars[pMLEditData->fit_chars] = pMLEditData->sz.cx;
}
static void edtGetLineInfo (HWND hWnd, PEBLINEDATA pLineData)
{
edtGetLineInfoEx (hWnd, NULL, pLineData);
}
static int edtGetStartDispPosAtEnd (HWND hWnd,
PEBLINEDATA pLineData)
{
PEBMLEDITDATA pMLEditData =(PEBMLEDITDATA) GetWindowAdditionalData2(hWnd);
int i = 0;
int dist = MAX_IMPOSSIBLE;
int newdist = 0;
edtGetLineInfo (hWnd, pLineData);
if (pMLEditData->sz.cx <= edtGetOutWidth (hWnd))
return 0;
for (i = 0; i < pMLEditData->fit_chars-1; i++)
{
newdist = (pMLEditData->sz.cx - edtGetOutWidth (hWnd)) - pMLEditData->dx_chars[i];
if (newdist >= 0 && newdist < dist)
{
dist = newdist;
if (dist == 0)
return i;
}
else
return i;
}
return 0;
}
void calcLineInfo(HWND hWnd, PEBMLEDITDATA pMLEditData, PEBLINEDATA pLineData)
{
int i;
edtGetLineInfoEx (hWnd, pMLEditData, pLineData);
for ( i=0,pLineData->nwrapline=1,pLineData->wrapStartPos[0]=0;
(i = edtGetnextStartPos(hWnd, pMLEditData,i)) > 0;
pLineData->nwrapline++ )
{
pLineData->wrapStartPos[pLineData->nwrapline] = i;
}
pLineData->wrapStartPos[pLineData->nwrapline] = pMLEditData->fit_chars;
}
void MLEditInitBuffer (HWND hWnd, PEBMLEDITDATA pMLEditData, const char *spcaption, DWORD dwStyle)
{
char *caption=(char*)spcaption;
int off1;
int lineNO=0;
PEBLINEDATA pLineData;
if (!(pMLEditData->head = calloc (1, sizeof (EBLINEDATA)))) {
return ;
}
pMLEditData->head->previous = NULL;
pLineData = pMLEditData->head;
pMLEditData->wraplines = 0;
while ( (off1 = GetRETURNPos(caption)) != -1)
{
int off;
off1 = MIN (off1, LEN_MLEDIT_BUFFER);
if ((char)caption[off1-1] == '\r')
off = off1-1;
else
off = off1;
if ((pMLEditData->curtotalLen + MIN (off,LEN_MLEDIT_BUFFER) >= pMLEditData->totalLimit)
&& pMLEditData->totalLimit != -1)
{
pLineData->dataEnd = pMLEditData->totalLimit-pMLEditData->curtotalLen;
caption += MIN (pLineData->dataEnd, LEN_MLEDIT_BUFFER) + 1;
if (pLineData->dataEnd-2 > 0 && (char)caption[pLineData->dataEnd-2] == '\r')
pLineData->dataEnd -= 2;
else if (pLineData->dataEnd-1 > 0 && (char)caption[pLineData->dataEnd-1] == '\n')
pLineData->dataEnd --;
memcpy(pLineData->buffer,caption, pLineData->dataEnd);
pLineData->buffer[pLineData->dataEnd] = '\0';
pLineData->lineNO = lineNO++;
pMLEditData->curtotalLen += pLineData->dataEnd;
if (!pLineData->dataEnd)
{
pLineData->nwrapline = 1;
pLineData->wrapStartPos[0] = 0;
pLineData->wrapStartPos[1] = 0;
} else
calcLineInfo (hWnd, pMLEditData, pLineData);
pMLEditData->wraplines += pLineData->nwrapline;
pLineData->lineNO = lineNO++;
if (pMLEditData->curtotalLen == pMLEditData->totalLimit)
{
pLineData->next = NULL;
break;
} else if (pMLEditData->curtotalLen + 1 < pMLEditData->totalLimit)
pMLEditData->curtotalLen ++;
pLineData->next = malloc (sizeof (EBLINEDATA));
pLineData->next->previous = pLineData;
pLineData->next->next = NULL;
pLineData = pLineData->next;
break;
}
memcpy(pLineData->buffer,caption, off1);
if (pLineData->buffer[off1-1] == '\r')
pLineData->buffer[off1-1] = '\0';
else
pLineData->buffer[off1] = '\0';
caption += MIN (off1,LEN_MLEDIT_BUFFER)+1;
pLineData->lineNO = lineNO++;
pLineData->dataEnd = strlen(pLineData->buffer);
if (!pLineData->dataEnd)
{
pLineData->nwrapline = 1;
pLineData->wrapStartPos[0] = 0;
pLineData->wrapStartPos[1] = 0;
}
else
calcLineInfo (hWnd, pMLEditData, pLineData);
pMLEditData->wraplines += pLineData->nwrapline;
pMLEditData->curtotalLen += pLineData->dataEnd;
if (pMLEditData->curtotalLen == pMLEditData->totalLimit)
{
pLineData->next = NULL;
break;
} else if (pMLEditData->curtotalLen + 1 < pMLEditData->totalLimit)
pMLEditData->curtotalLen ++;
pLineData->next = malloc(sizeof (EBLINEDATA));
pLineData->next->previous = pLineData;
pLineData->next->next = NULL;
pLineData = pLineData->next;
}
if (pMLEditData->totalLimit > 0 && pMLEditData->curtotalLen < pMLEditData->totalLimit)
{
int off=0;
off1 = MIN(strlen(caption), LEN_MLEDIT_BUFFER);
if (off1 && (char)caption[off1-1] == '\r')
off = off1-1;
else
off = off1;
if (pMLEditData->curtotalLen + MIN (off,LEN_MLEDIT_BUFFER) >= pMLEditData->totalLimit)
{
pLineData->dataEnd = pMLEditData->totalLimit-pMLEditData->curtotalLen;
if (pLineData->dataEnd-2 > 0 && (char)caption[pLineData->dataEnd-2] == '\r')
pLineData->dataEnd -= 2;
else if (pLineData->dataEnd-1 > 0 && (char)caption[pLineData->dataEnd-1] == '\n')
pLineData->dataEnd --;
memcpy(pLineData->buffer,caption, pLineData->dataEnd);
pLineData->buffer[pLineData->dataEnd] = '\0';
}
else
{
memcpy(pLineData->buffer, caption, off1);
if (off1 && pLineData->buffer[off1-1] == '\r')
pLineData->buffer[off1-1] = '\0';
else
pLineData->buffer[off1] = '\0';
pLineData->dataEnd = strlen(pLineData->buffer);
pLineData->next = NULL;
}
pMLEditData->curtotalLen += pLineData->dataEnd;
if (pMLEditData->curtotalLen == pMLEditData->totalLimit-1)
pMLEditData->curtotalLen = pMLEditData->totalLimit;
if (!pLineData->dataEnd)
{
pLineData->nwrapline = 1;
pLineData->wrapStartPos[0] = 0;
pLineData->wrapStartPos[1] = 0;
}
else
calcLineInfo (hWnd, pMLEditData, pLineData);
pMLEditData->wraplines += pLineData->nwrapline;
pLineData->lineNO = lineNO++;
}
pMLEditData->lines = lineNO;
if (dwStyle & EES_AUTOWRAP)
pMLEditData->linesDisp = MIN(pMLEditData->wraplines, pMLEditData->MaxlinesDisp);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -