📄 medit.c
字号:
/*
* Copyright (C) 1999, 2000, Wei Yongming.
* Portions Copyright (c) 2000 Greg Haerr <greg@censoft.com>
*
* Multi Line Edit Control for Microwindows win32 api.
*/
/*
** 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.
*/
/* Note:
** Although there was a version by Zhao Jianghua, this version of
** EDIT control is written by Wei Yongming from scratch.
**
** Create date: 1999/8/26
**
** Modify records:
**
** Who When Where For What Status
**-----------------------------------------------------------------------------
** WEI Yongming 2000/02/24 Tsinghua Add MPL License Finished
** Kevin Tseng 2000/08/30 gv port to microwin ported
**
**
** TODO:
** * Selection.
** * Undo.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#define MWINCLUDECOLORS
#include "windows.h" /* windef.h, winuser.h */
#include "wintools.h"
#include "device.h" /* GdGetTextSize */
#define USE_BIG5
#define WIDTH_MEDIT_BORDER 2
#define MARGIN_MEDIT_LEFT 1
#define MARGIN_MEDIT_TOP 1
#define MARGIN_MEDIT_RIGHT 2
#define MARGIN_MEDIT_BOTTOM 1
#define LEN_MLEDIT_BUFFER 3000
#define LEN_MLEDIT_UNDOBUFFER 1024
#define EST_FOCUSED 0x00000001L
#define EST_MODIFY 0x00000002L
#define EST_READONLY 0x00000004L
#define EST_REPLACE 0x00000008L
#define MEDIT_OP_NONE 0x00
#define MEDIT_OP_DELETE 0x01
#define MEDIT_OP_INSERT 0x02
#define MEDIT_OP_REPLACE 0x03
typedef struct tagLINEDATA {
int lineNO; /* 行号 */
int dataEnd;
struct tagLINEDATA *previous; /* 前一行 */
struct tagLINEDATA *next; /* 后一行 */
char buffer[LEN_MLEDIT_BUFFER+1];
}LINEDATA;
typedef LINEDATA* PLINEDATA;
#define ATTENG 0 /* english */
#define ATTCHL 1 /* chinese left(1st) byte */
#define ATTCHR 2 /* chinese right(2nd) byte */
static char attr[LEN_MLEDIT_BUFFER];
typedef struct tagMLEDITDATA {
int totalLen; /* length of buffer,可能没有用 */
int editPos; /* current edit position */
int caretPos; /* caret offset in box */
int editLine; /* current eidt line */
int dispPos; /* 开始显示的位置 */
int StartlineDisp; /* start line displayed */
int EndlineDisp; /* end line displayed */
int linesDisp; /* 需要显示的行数 */
int lines; /* 总的行数` */
int MaxlinesDisp; /* 最大显示的行数. */
int selStartPos; /* selection start position */
int selStartLine; /* selection start line */
int selEndPos; /* selection end position */
int selEndLine; /* selection end line */
int passwdChar; /* password character */
int leftMargin; /* left margin */
int topMargin; /* top margin */
int rightMargin; /* right margin */
int bottomMargin; /* bottom margin */
int hardLimit; /* hard limit */
int lastOp; /* last operation */
int lastPos; /* last operation position */
int lastLine; /* last operation line */
int affectedLen; /* affected len of last operation */
int undoBufferLen; /* undo buffer len */
char undoBuffer [LEN_MLEDIT_UNDOBUFFER];
/* Undo buffer; */
PLINEDATA head; /* buffer */
PLINEDATA tail; /* 可能不需要 */
}MLEDITDATA;
typedef MLEDITDATA* PMLEDITDATA;
BOOL RegisterMLEditControl (void);
int MLEditCtrlProc (HWND hWnd, int message, WPARAM wParam, LPARAM lParam);
#define PIXEL_invalid (-1)
extern HWND sg_hCaretWnd;
extern HWND rootwp;
static int GetSysCharHeight (HWND hwnd)
{
#ifndef USE_BIG5
HDC hdc;
int xw, xh, xb;
hdc = GetDC(hwnd);
SelectObject(hdc, GetStockObject(DEFAULT_FONT));
GdSetFont(hdc->font->pfont);
GdGetTextSize(hdc->font->pfont,"X",1, &xw,&xh,&xb,MWTF_ASCII);
ReleaseDC(hwnd,hdc);
return xh;
#else
return 12;
#endif
}
static int GetSysCharWidth (HWND hwnd)
{
#ifndef USE_BIG5
HDC hdc;
int xw, xh, xb;
hdc = GetDC(hwnd);
SelectObject(hdc, GetStockObject(DEFAULT_FONT));
GdSetFont(hdc->font->pfont);
GdGetTextSize(hdc->font->pfont,"X",1, &xw,&xh,&xb,MWTF_ASCII);
ReleaseDC(hwnd,hdc);
return xw;
#else
return 6;
#endif
}
static int GetSysCCharWidth (HWND hwnd)
{
return (2*GetSysCharWidth(hwnd));
}
char* GetWindowCaption (HWND hWnd)
{
return hWnd->szTitle;
}
DWORD GetWindowAdditionalData (HWND hWnd)
{
return hWnd->userdata;
}
DWORD SetWindowAdditionalData (HWND hWnd, DWORD newData)
{
DWORD oldOne = 0L;
oldOne = hWnd->userdata;
hWnd->userdata = newData;
return oldOne;
}
DWORD GetWindowAdditionalData2 (HWND hWnd)
{
return hWnd->userdata2;
}
DWORD SetWindowAdditionalData2 (HWND hWnd, DWORD newData)
{
DWORD oldOne = 0L;
oldOne = hWnd->userdata2;
hWnd->userdata2 = newData;
return oldOne;
}
DWORD GetWindowStyle (HWND hWnd)
{
return hWnd->style;
}
BOOL ExcludeWindowStyle (HWND hWnd, DWORD dwStyle)
{
if (hWnd == rootwp/*HWND_DESKTOP*/)
return FALSE;
hWnd->style &= ~dwStyle;
return TRUE;
}
BOOL IncludeWindowStyle (HWND hWnd, DWORD dwStyle)
{
if (hWnd == rootwp/*HWND_DESKTOP*/)
return FALSE;
hWnd->style |= dwStyle;
return TRUE;
}
int WINAPI MwRegisterMEditControl(HINSTANCE hInstance)
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_GLOBALCLASS;
wc.lpfnWndProc = (WNDPROC)MLEditCtrlProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = 0;
wc.hbrBackground= GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName= "MEDIT";
return RegisterClass(&wc);
}
static inline int edtGetOutWidth (HWND hWnd)
{
PMLEDITDATA pMLEditData =(PMLEDITDATA) GetWindowAdditionalData2(hWnd);
RECT rc;
GetClientRect(hWnd,&rc);
return rc.right - rc.left
- pMLEditData->leftMargin
- pMLEditData->rightMargin;
}
static int edtGetStartDispPosAtEnd (HWND hWnd,
PLINEDATA pLineData)
{
int nOutWidth = edtGetOutWidth (hWnd);
int endPos = pLineData->dataEnd;
PMLEDITDATA pMLEditData =(PMLEDITDATA) GetWindowAdditionalData2(hWnd);
int newStartPos = pMLEditData->dispPos;
const char* buffer = pLineData->buffer;
if(endPos < newStartPos)
return 0;
while (TRUE)
{
if ((endPos - newStartPos) * GetSysCharWidth (hWnd) < nOutWidth)
break;
/* 1st:gb:a1-f7,big5:a1-f9 */
if ((BYTE)buffer [newStartPos] > 0xA0)
{
newStartPos ++;
if (newStartPos < pLineData->dataEnd)
{
#ifndef USE_BIG5
if ((BYTE)buffer [newStartPos] > 0xA0)
#else /* 2nd:gb:a1-fe,big5:40-7e,a1-fe */
if ( ((BYTE)buffer [newStartPos] >= 0x40 && (BYTE)buffer[newStartPos] <= 0x7e) ||
((BYTE)buffer [newStartPos] >= 0xa1 && (BYTE)buffer[newStartPos] <= 0xfe))
#endif
newStartPos ++;
}
}
else
newStartPos ++;
}
return newStartPos;
}
static int edtGetDispLen (HWND hWnd,PLINEDATA pLineData)
{
int i, n = 0;
int nOutWidth = edtGetOutWidth (hWnd);
int nTextWidth = 0;
PMLEDITDATA pMLEditData =(PMLEDITDATA) GetWindowAdditionalData2(hWnd);
const char* buffer = pLineData->buffer;
if(buffer[0]==0||pLineData->dataEnd<pMLEditData->dispPos)
return 0;
for (i = pMLEditData->dispPos; i < pLineData->dataEnd; i++)
{
/* 1st:gb:a1-f7,big5:a1-f9 */
if ((BYTE)buffer [i] > 0xA0)
{
i++;
if (i < pLineData->dataEnd)
{
#ifndef USE_BIG5
if ((BYTE)buffer [i] > 0xA0) /* 2nd:gb:a1-fe,big5:40-7e,a1-fe */
#else /* 2nd:gb:a1-fe,big5:40-7e,a1-fe */
if ( ((BYTE)buffer [i] >= 0x40 && (BYTE)buffer[i] <= 0x7e) ||
((BYTE)buffer [i] >= 0xa1 && (BYTE)buffer[i] <= 0xfe))
#endif
{
nTextWidth += GetSysCCharWidth (hWnd);
n += 2;
}
else
i--;
}
else
{
nTextWidth += GetSysCharWidth (hWnd);
n++;
}
}
else
{
nTextWidth += GetSysCharWidth (hWnd);
n++;
}
if (nTextWidth > nOutWidth)
break;
}
return n;
}
static int edtGetOffset (HWND hwnd,const MLEDITDATA* pMLEditData, PLINEDATA pLineData, int x)
{
int i;
int newOff = 0;
int nTextWidth = 0;
const char* buffer = pLineData->buffer;
if(pLineData->dataEnd<pMLEditData->dispPos)
return pLineData->dataEnd;
x -= pMLEditData->leftMargin;
for (i = pMLEditData->dispPos; i < pLineData->dataEnd; i++) {
if ((nTextWidth + (GetSysCharWidth(hwnd) >> 1)) >= x)
break;
/* 1st:gb:a1-f7,big5:a1-f9 */
if ((BYTE)buffer [i] > 0xA0)
{
i++;
if (nTextWidth + GetSysCCharWidth(hwnd)/2 >= x)
break;
if (i < pLineData->dataEnd)
{
#ifndef USE_BIG5
if ((BYTE)buffer [i] > 0xA0) /* 2nd:gb:a1-fe,big5:40-7e,a1-fe */
#else /* 2nd:gb:a1-fe,big5:40-7e,a1-fe */
if ( ((BYTE)buffer [i] >= 0x40 && (BYTE)buffer[i] <= 0x7e) ||
((BYTE)buffer [i] >= 0xa1 && (BYTE)buffer[i] <= 0xfe))
#endif
{
nTextWidth += GetSysCCharWidth (hwnd);
newOff += 2;
}
else
i --;
}
else
{
nTextWidth += GetSysCharWidth (hwnd);
newOff ++;
}
}
else
{
nTextWidth += GetSysCharWidth (hwnd);
newOff ++;
}
}
return newOff;
}
static int edtGetLineNO (HWND hwnd,const MLEDITDATA* pMLEditData, int x)
{
int nline = 0;
if(x>=0)
{
nline = x / GetSysCharHeight(hwnd);
if (nline <= pMLEditData->linesDisp)
return nline;
}
return -1;
}
static BOOL edtIsACCharAtPosition (const char* string, int len, int pos)
{
if (pos > (len - 2))
return FALSE;
/* 1st:gb:a1-f7,big5:a1-f9 2nd:gb:a1-fe,big5:40-7e,a1-fe */
#ifndef USE_BIG5
if ((BYTE)string [pos] > 0xA0 && (BYTE)string [pos + 1] > 0xA0)
return TRUE;
#else
if ((BYTE)string [pos] > 0xA0)
{
if ( ((BYTE)string [pos + 1] >= 0x40 && (BYTE)string [pos + 1] <= 0x7e) ||
((BYTE)string [pos + 1] >= 0xa1 && (BYTE)string [pos + 1] <= 0xfe)) {
/*fprintf(stderr,"true\n");
fflush(stderr);*/
return TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -