📄 edit.c
字号:
/*
** $Id: edit.c,v 1.101 2004/09/28 01:23:55 snig Exp $
**
** edit.c: the Single Line Edit Control module.
**
** Copyright (C) 2003 Feynman Software.
** Copyright (C) 1999 ~ 2002 Wei Yongming.
**
** Current maintainer: Wei Yongming.
**
** 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
*/
/*
** 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:
** * Replace
** * Undo.
**/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "common.h"
#include "minigui.h"
#include "gdi.h"
#include "window.h"
#include "control.h"
#include "cliprect.h"
#include "internals.h"
#include "ctrlclass.h"
#include "clipboard.h"
#ifdef _CTRL_SLEDIT
#include "ctrlmisc.h"
#include "text.h"
#include "edit.h"
static int SLEditCtrlProc (HWND hWnd, int message, WPARAM wParam, LPARAM lParam);
#define check_caret() \
if(sled->selStart != sled->selEnd) \
HideCaret(hWnd); \
else \
ShowCaret(hWnd);
#define shift_one_char_r(pos) \
{ \
int len = CHLENNEXT( (sled->content.string + sled->pos), (sled->content.txtlen - sled->pos)); \
sled->pos += len; \
}
#define shift_one_char_l(pos) \
{ \
int len = CHLENPREV( sled->content.string, (sled->content.string + sled->pos) ); \
sled->pos -= len; \
}
BOOL RegisterSLEditControl (void)
{
WNDCLASS WndClass;
WndClass.spClassName = CTRL_SLEDIT;
WndClass.dwStyle = WS_NONE;
WndClass.dwExStyle = WS_EX_NONE;
WndClass.hCursor = GetSystemCursor (IDC_IBEAM);
WndClass.iBkColor = GetWindowElementColor (BKC_EDIT_DEF);
WndClass.WinProc = SLEditCtrlProc;
return AddNewControlClass (&WndClass) == ERR_OK;
}
/* -------------------------------------------------------------------------- */
static void setup_dc (HWND hWnd, SLEDITDATA *sled, HDC hdc, BOOL bSel)
{
DWORD dwStyle = GetWindowStyle (hWnd);
if (!bSel) {
if (dwStyle & WS_DISABLED)
SetTextColor (hdc, GetWindowElementColorEx (hWnd, FGC_CONTROL_DISABLED));
else
SetTextColor (hdc, GetWindowElementColorEx (hWnd, FGC_CONTROL_NORMAL));
SetBkMode (hdc, BM_TRANSPARENT);
}
else {
if (dwStyle & WS_DISABLED)
SetTextColor (hdc, GetWindowElementColorEx (hWnd, FGC_HILIGHT_DISABLED));
else
SetTextColor (hdc, GetWindowElementColorEx (hWnd, FGC_HILIGHT_NORMAL));
if (sled->status & EST_FOCUSED)
SetBkColor (hdc, GetWindowElementColorEx (hWnd, BKC_HILIGHT_NORMAL));
else
SetBkColor (hdc, GetWindowElementColorEx (hWnd, BKC_HILIGHT_LOSTFOCUS));
SetBkMode (hdc, BM_OPAQUE);
}
}
/* -------------------------------------------------------------------------- */
static int sledit_settext (PSLEDITDATA sled, const char *newtext)
{
int len, txtlen;
txtlen = strlen (newtext);
len = (txtlen <= 0) ? sled->nBlockSize : txtlen;
if (sled->hardLimit >= 0) {
len = MIN (len, sled->hardLimit);
txtlen = MIN (txtlen, sled->hardLimit);
}
/* free the old text */
if (sled->content.string)
testr_free (&sled->content);
if (!testr_alloc (&sled->content, len, sled->nBlockSize))
return -1;
if (newtext && txtlen > 0)
testr_setstr (&sled->content, newtext, txtlen);
else
sled->content.txtlen = 0;
return 0;
}
static void get_content_width (HWND hWnd, PSLEDITDATA sled)
{
GetClientRect (hWnd, &sled->rcCont);
sled->rcCont.left += sled->leftMargin;
sled->rcCont.top += sled->topMargin;
sled->rcCont.right -= sled->rightMargin;
sled->rcCont.bottom -= sled->bottomMargin;
sled->starty = sled->topMargin + ( sled->rcCont.bottom -
sled->rcCont.top - GetWindowFont (hWnd)->size - 1 ) / 2;
}
static int sledit_init (HWND hWnd, PSLEDITDATA sled)
{
if (!sled)
return -1;
SetWindowAdditionalData2 (hWnd,(DWORD)sled);
sled->status = 0;
sled->editPos = 0;
sled->selStart = 0;
sled->selEnd = 0;
sled->leftMargin = MARGIN_EDIT_LEFT;
sled->topMargin = MARGIN_EDIT_TOP;
sled->rightMargin = MARGIN_EDIT_RIGHT;
sled->bottomMargin = MARGIN_EDIT_BOTTOM;
get_content_width (hWnd, sled);
sled->nContX = 0;
sled->nContW = sled->rcCont.right - sled->rcCont.left;
sled->passwdChar = '*';
sled->nBlockSize = DEF_LINE_BLOCK_SIZE;
sled->hardLimit = -1;
if (GetWindowStyle(hWnd) & ES_TIP) {
sled->tiptext = FixStrAlloc (DEF_TIP_LEN + 1);
sled->tiptext[0] = 0;
}
else
sled->tiptext = NULL;
sled->content.string = NULL;
sled->content.buffsize = 0;
sled->content.txtlen = 0;
sledit_settext (sled, GetWindowCaption(hWnd));
CreateCaret (hWnd, NULL, 1, GetWindowFont (hWnd)->size);
SetCaretPos (hWnd, sled->leftMargin, sled->starty);
return 0;
}
static void sledit_destroy (HWND hWnd, PSLEDITDATA sled)
{
DestroyCaret (hWnd);
if ( (GetWindowStyle(hWnd) & ES_TIP) && sled->tiptext)
FreeFixStr (sled->tiptext);
testr_free (&sled->content);
}
static void slePaint (HWND hWnd, HDC hdc, PSLEDITDATA sled)
{
char* dispBuffer, *passwdBuffer = NULL;
DWORD dwStyle = GetWindowStyle(hWnd);
StrBuffer *content = &sled->content;
int starty = sled->starty;
int outw = 0;
if (dwStyle & ES_TIP && content->txtlen <= 0 &&
GetFocus(GetParent(hWnd)) != hWnd) {
setup_dc (hWnd, sled, hdc, FALSE);
TextOut (hdc, sled->leftMargin, starty,
sled->tiptext);
return;
}
if (dwStyle & ES_PASSWORD) {
dispBuffer = FixStrAlloc (content->txtlen);
memset (dispBuffer, sled->passwdChar, content->txtlen);
passwdBuffer = dispBuffer;
}
else {
dispBuffer = content->string;
}
if (dwStyle & ES_BASELINE) {
SetPenColor (hdc, GetWindowElementColorEx (hWnd, FGC_CONTROL_NORMAL));
#ifdef _PHONE_WINDOW_STYLE
MoveTo (hdc, sled->leftMargin, sled->rcCont.bottom);
LineTo (hdc, sled->rcCont.right, sled->rcCont.bottom);
#else
DrawHDotLine (hdc,
sled->leftMargin,
sled->rcCont.bottom,
sled->rcCont.right - sled->rcCont.left);
#endif
}
ClipRectIntersect (hdc, &sled->rcCont);
if (sled->selStart != sled->selEnd) {//select chars
int startx = sled->leftMargin - sled->nContX;
/* draw first normal chars */
if (sled->selStart > 0) {
setup_dc (hWnd, sled, hdc, FALSE);
outw += TextOutLen (hdc, startx, starty,
dispBuffer, sled->selStart);
dispBuffer += sled->selStart;
}
/* draw selected chars */
setup_dc (hWnd, sled, hdc, TRUE);
outw += TextOutLen (hdc, startx + outw, starty, dispBuffer,
sled->selEnd - sled->selStart);
dispBuffer += sled->selEnd - sled->selStart;
/* draw others */
if (sled->selEnd < content->txtlen) {
setup_dc (hWnd, sled, hdc, FALSE);
outw += TextOutLen (hdc, startx + outw, starty, dispBuffer, content->txtlen - sled->selEnd);
}
}
else {
setup_dc (hWnd, sled, hdc, FALSE);
outw += TextOutLen (hdc, sled->leftMargin - sled->nContX, starty,
dispBuffer, content->txtlen);
}
sled->nContW = outw;
if (sled->nContW < sled->rcCont.right - sled->rcCont.left)
sled->nContW = sled->rcCont.right - sled->rcCont.left;
if (dwStyle & ES_PASSWORD)
FreeFixStr (passwdBuffer);
}
static int sleSetSel (HWND hWnd, PSLEDITDATA sled, int sel_start, int sel_end)
{
if (sled->content.txtlen <= 0)
return -1;
if (sel_start < 0)
sel_start = 0;
if (sel_end < 0)
sel_end = sled->content.txtlen;
if (sel_start == sel_end)
return -1;
sled->selStart = sel_start;
sled->selEnd = sel_end;
HideCaret(hWnd);
InvalidateRect(hWnd, NULL, TRUE);
return sled->selEnd - sled->selStart;
}
static void set_caret_pos (HWND hWnd, PSLEDITDATA sled, int x, BOOL bSel)
{
int out_chars;
HDC hdc;
SIZE txtsize;
hdc = GetClientDC (hWnd);
if (x + sled->nContX <= 0) {
out_chars = 0;
txtsize.cx = 0;
}
else
out_chars = GetTextExtentPoint (hdc, sled->content.string, sled->content.txtlen,
x + sled->nContX, NULL, NULL, NULL, &txtsize);
if (!bSel) {
sled->selStart = sled->selEnd = 0;
sled->editPos = out_chars;
SetCaretPos (hWnd, txtsize.cx - sled->nContX, sled->starty);
}
else {
if (out_chars > sled->editPos) {
sled->selStart = sled->editPos;
sled->selEnd = out_chars;
}
else {
sled->selEnd = sled->editPos;
sled->selStart = out_chars;
}
}
ReleaseDC (hdc);
}
static BOOL make_pos_visible (HWND hWnd, PSLEDITDATA sled, int x)
{
if (x - sled->nContX > sled->rcCont.right - sled->rcCont.left) {
//FIXME
sled->nContX = x - (sled->rcCont.right - sled->rcCont.left - 3);
return TRUE;
}
else if (x < sled->nContX) {
sled->nContX = x;
return TRUE;
}
return FALSE;
}
static BOOL make_charpos_visible (HWND hWnd, PSLEDITDATA sled, int charPos, int *cx)
{
SIZE txtsize;
HDC hdc;
if (charPos <= 0)
txtsize.cx = 0;
else {
hdc = GetClientDC (hWnd);
GetTextExtent (hdc, sled->content.string, charPos, &txtsize);
ReleaseDC (hdc);
}
if (cx)
*cx = txtsize.cx;
return make_pos_visible (hWnd, sled, txtsize.cx);
}
static BOOL edtSetCaretPos (HWND hWnd, PSLEDITDATA sled)
{
BOOL bRefresh;
int cx;
bRefresh = make_charpos_visible (hWnd, sled, sled->editPos, &cx);
SetCaretPos (hWnd, sled->leftMargin + cx - sled->nContX, sled->starty);
if (bRefresh)
InvalidateRect (hWnd, NULL, TRUE);
return bRefresh;
}
/*
static void get_cont_x (HWND hWnd, PSLEDITDATA sled)
{
HDC hdc;
SIZE txtsize;
hdc = GetClientDC (hWnd);
if (sled->startPos == 0)
sled->nContX = 0;
else {
GetTextExtent (hdc, sled->content.string, sled->startPos, &txtsize);
sled->nContX = txtsize.cx;
}
ReleaseDC (hdc);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -