📄 newedit.c
字号:
/* * NEW "EDIT control" for Microwindows win32 api. * * Copyright (C) 2003, Gabriele Brugnoni * <gabrielebrugnoni@dveprojects.com> * DVE Prog. El. - Varese, Italy * * Based on microwindows edit.c * Copyright (C) 1999, 2000, Wei Yongming. * Portions Copyright (c) 2000 Greg Haerr <greg@censoft.com> * *//* Note:**** Create date: 2003/09/02**** Modify records:**** Who When Where For What Status**-----------------------------------------------------------------------------**** TODO:** * BIG5 font and cinese support** * Multiline.** * UNICODE ??.*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#define MWINCLUDECOLORS#include "windows.h" /* windef.h, winuser.h */#include "wintern.h"#include "wintools.h"#include "device.h" /* GdGetTextSize */#include "intl.h"// NOTE: #if HAVE_HZK_SUPPORT || HAVE_BIG5_SUPPORT#define USE_BIG5#define DEFAULT_FONT SYSTEM_FIXED_FONT#else#define DEFAULT_FONT DEFAULT_GUI_FONT#endif#define WIDTH_EDIT_BORDER 2#define MARGIN_EDIT_LEFT 1#define MARGIN_EDIT_TOP 1#define MARGIN_EDIT_RIGHT 2#define MARGIN_EDIT_BOTTOM 1#define LEN_SLEDIT_BUFFER 256#define LEN_SLEDIT_ADDBUFFER 256#define LEN_SLEDIT_REMOVEBUFFER 1024 // if great than this, realloc#define LEN_SLEDIT_UNDOBUFFER 1024#define EST_FOCUSED 0x00000001L#define EST_MODIFY 0x00000002L#define EST_READONLY 0x00000004L#define EST_REPLACE 0x00000008L#define EST_CTRL 0x00000010L#define EST_SHIFT 0x00000020L#define EST_SELSCROLLLEFT 0x00000040L#define EST_SELSCROLLRIGHT 0x00000080L#define EDIT_OP_NONE 0x00#define EDIT_OP_DELETE 0x01#define EDIT_OP_INSERT 0x02#define EDIT_OP_REPLACE 0x03// Timers#define IDTM_SELSCROLLLEFT 0x101#define IDTM_SELSCROLLRIGHT 0x102#define TM_SELSCROLL 60 // timeout for scrollingchar mwDefEditCaretSize = 1;char mwDefEditCaretSizeIns = 3;typedef unsigned short EDITCHAR;#define SZEDITCHAR sizeof(EDITCHAR)/* * Edit structure */typedef struct tagSLEDITDATA { HFONT hFont; /* hFont used */ int bufferLen; /* length of buffer */ int dataEnd; /* data end position */ int editPos; /* current edit position */ int caretX; /* caret X position in box */ int caretRow; /* caret Y position in box */ int scrollX; /* X scrolling offset */ int scrollRow; /* Y scrolling offset */ int epX, epY; /* coordinates of edit position */ int epFirstIdx; /* index of the first character in line with editPos */ int epLineCount; /* count of characters in line with editPos */ int epLineOX; /* X origin of current line. Typically > 0 when right aligned */ int epLineAlign; /* Alignement of current line. 0 = left align, 1 = right align */ int selStart; /* selection start position */ int selEnd; /* selection end position */ int selCenter; /* selection cursor center */ int passwdChar; /* password character */ int charHeight; /* height of 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 affectedLen; /* affected len of last operation */ int undoBufferLen; /* undo buffer len */ EDITCHAR undoBuffer[LEN_SLEDIT_UNDOBUFFER]; /* Undo buffer; */ EDITCHAR *buffer; /* buffer */ int cLines; /* count of allocated (visible) lines info */} SLEDITDATA, *PSLEDITDATA;// For future implementation of unicode...#define edit_memcpy memcpy#define memcpy_fromedit memcpy#define neTextOut TextOutW#define neIsWord(c) ( (c) > 32 && (((c) > 127) || isalpha(c) || isdigit(c)) )// Drawing attributes#define NEDRAW_ENTIRE 0x0001#define NEDRAW_ROW 0x0002#define NEDRAW_CALC_CURSOR 0x0004#define NEDRAW_CALC_EDITPOS 0x0008static int neGetTextHeight(HWND hWnd, HDC hdc);static int neGetTextWith(HWND hWnd, HDC hdc, PSLEDITDATA pSLEditData, const EDITCHAR * txt, int len);static int neCharPressed(HWND hWnd, WPARAM wParam, LPARAM lParam);static void neRecalcRows(HWND hwnd, PSLEDITDATA * ppData);static void neDrawAllText(HWND hWnd, HDC hdc, PSLEDITDATA pSLEditData, int action);// Clipboard for cut and paste.static EDITCHAR *neClipboard = NULL;static int neClipboardSize = 0;/* * Create new edit control */static intneCreate(HWND hwnd){ PSLEDITDATA pSLEditData; HWND pCtrl = hwnd; int len; int charH; int nl; RECT rc; GetClientRect(hwnd, &rc); nl = (rc.bottom - rc.top + charH - 1) / charH; if (!(pSLEditData = malloc(sizeof(SLEDITDATA)))) { EPRINTF("EDIT: malloc error!\n"); return -1; } len = 1 + strlen(pCtrl->szTitle); if (len < LEN_SLEDIT_BUFFER) len = LEN_SLEDIT_BUFFER; pCtrl->userdata2 = (DWORD) pSLEditData; pCtrl->userdata = 0;#ifdef USE_BIG5 pSLEditData->hFont = CreateFont(12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, FF_DONTCARE | DEFAULT_PITCH, "HZXFONT");#else pSLEditData->hFont = GetStockObject(DEFAULT_FONT);#endif pSLEditData->bufferLen = len; pSLEditData->editPos = 0; pSLEditData->caretX = 0; pSLEditData->caretRow = 0; pSLEditData->scrollX = 0; pSLEditData->scrollRow = 0; pSLEditData->epFirstIdx = 0; pSLEditData->epLineCount = 0; pSLEditData->epLineOX = 0; pSLEditData->epLineAlign = 0; pSLEditData->selStart = 0; pSLEditData->selEnd = 0; pSLEditData->passwdChar = '*'; pSLEditData->leftMargin = MARGIN_EDIT_LEFT; pSLEditData->topMargin = MARGIN_EDIT_TOP; pSLEditData->rightMargin = MARGIN_EDIT_RIGHT; pSLEditData->bottomMargin = MARGIN_EDIT_BOTTOM; pSLEditData->hardLimit = -1; pSLEditData->buffer = (EDITCHAR *) malloc(SZEDITCHAR * pSLEditData->bufferLen); /* undo information */ pSLEditData->lastOp = EDIT_OP_NONE; pSLEditData->lastPos = 0; pSLEditData->affectedLen = 0; pSLEditData->undoBufferLen = LEN_SLEDIT_UNDOBUFFER; pSLEditData->undoBuffer[0] = '\0'; //edit_memcpy ( pSLEditData->buffer, pCtrl->szTitle, len ); pSLEditData->dataEnd = GdConvertEncoding(pCtrl->szTitle, mwTextCoding, strlen(pCtrl->szTitle), pSLEditData->buffer, MWTF_UC16); pSLEditData->charHeight = neGetTextHeight(hwnd, NULL); neRecalcRows(hwnd, &pSLEditData); return 0;}static voidneRecalcRows(HWND hwnd, PSLEDITDATA * ppData){ PSLEDITDATA pSLEditData; PSLEDITDATA pCurData = *ppData; RECT rc; int nl; int charH; charH = neGetTextHeight(hwnd, NULL); GetClientRect(hwnd, &rc); nl = (rc.bottom - rc.top + charH - 1) / charH; pSLEditData = (PSLEDITDATA) malloc(sizeof(SLEDITDATA)); if (pSLEditData == NULL) return; *pSLEditData = *pCurData; pSLEditData->charHeight = charH; pSLEditData->cLines = nl; *ppData = pSLEditData; hwnd->userdata2 = (DWORD) pSLEditData; free(pCurData);}/* * Destroy an edit control */static voidneDestroy(HWND hwnd){ PSLEDITDATA pSLEditData = (PSLEDITDATA) (hwnd->userdata2); free(pSLEditData->buffer); free(pSLEditData); hwnd->userdata2 = 0; DestroyCaret();}/* * Reallocate the buffer with the new size */static BOOLneReallocateBuffer(PSLEDITDATA pSLEditData, int len){ EDITCHAR *newbuff; if (len < pSLEditData->dataEnd) len = pSLEditData->dataEnd; newbuff = (EDITCHAR *) malloc(len * SZEDITCHAR); if (newbuff == NULL) { EPRINTF("Unable to allocate buffer for EDIT control.\n"); return FALSE; } memcpy(newbuff, pSLEditData->buffer, len * SZEDITCHAR); free(pSLEditData->buffer); pSLEditData->bufferLen = len; pSLEditData->buffer = newbuff; return TRUE;}/* * Check if it should reduce allocated buffer */static voidneCheckBufferSize(HWND hWnd, PSLEDITDATA pSLEditData){ if ((pSLEditData->bufferLen - pSLEditData->dataEnd) > LEN_SLEDIT_REMOVEBUFFER) neReallocateBuffer(pSLEditData, pSLEditData->dataEnd + LEN_SLEDIT_ADDBUFFER);}/* * Increment dataEnd and check if buffer should reallocated */static BOOLneIncDataEnd(PSLEDITDATA pSLEditData, int delta){ if ((pSLEditData->hardLimit >= 0) && (pSLEditData->dataEnd + delta >= pSLEditData->hardLimit)) return FALSE; pSLEditData->dataEnd += delta; if (pSLEditData->dataEnd > pSLEditData->bufferLen) { if (!neReallocateBuffer(pSLEditData, pSLEditData->bufferLen + LEN_SLEDIT_ADDBUFFER)) { pSLEditData->dataEnd -= delta; return FALSE; } } return TRUE;}/* * Copy selection to clipboard */static BOOLneCopyToCliboard(HWND hWnd, PSLEDITDATA pSLEditData){ if (pSLEditData->selStart < pSLEditData->selEnd) { int count = pSLEditData->selEnd - pSLEditData->selStart; if (count + pSLEditData->selStart > pSLEditData->dataEnd) count = pSLEditData->dataEnd - pSLEditData->selStart; if (count > 0) { if (neClipboard != NULL) free(neClipboard); neClipboard = (EDITCHAR *) malloc(count * SZEDITCHAR); if (neClipboard == NULL) return FALSE; memcpy(neClipboard, pSLEditData->buffer + pSLEditData->selStart, count * SZEDITCHAR); neClipboardSize = count; return TRUE; } } return FALSE;}static voidneUpdateCaretPos(HWND hWnd){ PSLEDITDATA pSLEditData = (PSLEDITDATA) (hWnd->userdata2); SetCaretPos(pSLEditData->caretX, pSLEditData->topMargin + pSLEditData->caretRow * pSLEditData->charHeight);}/* * Parse WM_SETTEXT command */static BOOLneSetText(HWND hWnd, const char *text){ //DWORD dwStyle = hWnd->style; PSLEDITDATA pSLEditData = (PSLEDITDATA) (hWnd->userdata2); int len; //FIXME: consider UTF8 len = strlen(text); if (pSLEditData->hardLimit >= 0) len = min(len, pSLEditData->hardLimit); if (len > pSLEditData->bufferLen) { if (!neReallocateBuffer(pSLEditData, len)) return FALSE; } pSLEditData->dataEnd = GdConvertEncoding(text, mwTextCoding, len, pSLEditData->buffer, MWTF_UC16); //edit_memcpy ( pSLEditData->buffer, text, len ); neCheckBufferSize(hWnd, pSLEditData); pSLEditData->editPos = 0; pSLEditData->scrollX = 0; pSLEditData->caretX = 0; pSLEditData->scrollRow = 0; pSLEditData->caretRow = 0; if ((hWnd->userdata & EST_FOCUSED)) neUpdateCaretPos(hWnd); InvalidateRect(hWnd, NULL, FALSE); return TRUE;}/* * Set FONT */static voidneSetFont(HWND hWnd, HFONT hFont, BOOL bRedraw){ PSLEDITDATA pSLEditData = (PSLEDITDATA) (hWnd->userdata2); pSLEditData->hFont = (HFONT) hFont; neRecalcRows(hWnd, &pSLEditData); ShowWindow(hWnd, SW_HIDE); ShowWindow(hWnd, SW_SHOWNA); if (bRedraw) InvalidateRect(hWnd, NULL, TRUE);}/* * Calculate the password chr with */static intneGetPasswdCharWith(HDC hdc, EDITCHAR pwdChar){ int xw, xh, xb; GdSetFont(hdc->font->pfont); GdGetTextSize(hdc->font->pfont, &pwdChar, 1, &xw, &xh, &xb, MWTF_UC16); return xw;}/* * Get height of character */static intneGetTextHeight(HWND hWnd, HDC hdc){ int xw, xh, xb; BOOL bRelDC = FALSE; if (hdc == NULL) hdc = GetDC(hWnd), bRelDC = TRUE; SelectObject(hdc, ((PSLEDITDATA) (hWnd->userdata2))->hFont); GdSetFont(hdc->font->pfont); GdGetTextSize(hdc->font->pfont, "X", 1, &xw, &xh, &xb, MWTF_ASCII); if (bRelDC) ReleaseDC(hWnd, hdc); return xh;}/* * Calculate a string with */static intneGetTextWith(HWND hWnd, HDC hdc, PSLEDITDATA pSLEditData, const EDITCHAR * txt, int len){ int xw, xh, xb; DWORD dwStyle = hWnd->style; BOOL bRelDC = FALSE; if (dwStyle & dwStyle & ES_PASSWORD) return len * neGetPasswdCharWith(hdc, pSLEditData->passwdChar); if (hdc == NULL) hdc = GetDC(hWnd), bRelDC = TRUE; SelectObject(hdc, pSLEditData->hFont); GdSetFont(hdc->font->pfont); GdGetTextSize(hdc->font->pfont, txt, len, &xw, &xh, &xb, MWTF_UC16); if (bRelDC) ReleaseDC(hWnd, hdc); return xw;}/* * Calculate client area width */static intedtGetOutWidth(const HWND pCtrl){ return pCtrl->clirect.right - pCtrl->clirect.left - ((PSLEDITDATA) (pCtrl->userdata2))->leftMargin - ((PSLEDITDATA) (pCtrl->userdata2))->rightMargin;}/* * Output a string in a PASSWORD EDIT */static voidneTextOutPwd(HDC hdc, int x, int y, EDITCHAR pwdChar, int len){ int i, xs; xs = neGetPasswdCharWith(hdc, pwdChar); for (i = 0; i < len; i++) { neTextOut(hdc, x, y, &pwdChar, 1); x += xs; }}/* * Determine the index position based on coords * When exit, the pPoint is set to the position * that the caret should be moved on. */static intneIndexFromPos(HWND hWnd, POINT * pPoint){ PSLEDITDATA pSLEditData = (PSLEDITDATA) (hWnd->userdata2); HDC hdc = GetDC(hWnd); int i, txts; SelectObject(hdc, pSLEditData->hFont); pPoint->x -= pSLEditData->leftMargin + 2; pPoint->y -= pSLEditData->topMargin; for (i = 0, txts = 0; i <= pSLEditData->dataEnd; i++) { txts = neGetTextWith(hWnd, hdc, pSLEditData, pSLEditData->buffer, i); if (txts >= (pPoint->x + pSLEditData->scrollX)) break; } if (i > pSLEditData->dataEnd) i = pSLEditData->dataEnd; pPoint->x = txts - pSLEditData->scrollX + pSLEditData->leftMargin; ReleaseDC(hWnd, hdc); return i;}/* * Check if scroll pos should be changed. * Return nonzero if the entire window should be redrawn */static BOOLneRecalcScrollPos(HWND hWnd, HDC hdc, PSLEDITDATA pSLEditData, BOOL checkNewline){ int xs; int lastscrollX; int lastscrollR; int pfirst, palign; lastscrollX = pSLEditData->scrollX; lastscrollR = pSLEditData->scrollRow; xs = edtGetOutWidth(hWnd); pfirst = pSLEditData->epFirstIdx; palign = pSLEditData->epLineAlign; neDrawAllText(hWnd, hdc, pSLEditData, NEDRAW_CALC_CURSOR); if (pSLEditData->epX < pSLEditData->scrollX) pSLEditData->scrollX = pSLEditData->epX; else if ((pSLEditData->epX - pSLEditData->scrollX - (pSLEditData->epLineAlign ? 2 : 0)) > xs) { int scrollStep = (pSLEditData->epX - pSLEditData->scrollX) - xs; if ((pSLEditData->editPos < pSLEditData->dataEnd) && (scrollStep < (xs / 2)) && !(hWnd-> userdata & (EST_SELSCROLLLEFT | EST_SELSCROLLRIGHT)) ) scrollStep = xs / 2; pSLEditData->scrollX += scrollStep; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -