1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240 |
- #include "main.h"
- #include "./embeddedEditor.h"
- #include <vector>
- #define EMBEDDEDEDITOR_FRAME_LEFT 1
- #define EMBEDDEDEDITOR_FRAME_TOP 1
- #define EMBEDDEDEDITOR_FRAME_RIGHT 1
- #define EMBEDDEDEDITOR_FRAME_BOTTOM 1
- #define EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_LEFT 1
- #define EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_TOP 1
- #define EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_RIGHT 1
- #define EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_BOTTOM 1
- #define EMBEDDEDEDITOR_FRAME_INNER_SPACE_LEFT 0
- #define EMBEDDEDEDITOR_FRAME_INNER_SPACE_TOP 0
- #define EMBEDDEDEDITOR_FRAME_INNER_SPACE_RIGHT 0
- #define EMBEDDEDEDITOR_FRAME_INNER_SPACE_BOTTOM 0
- #define EMBEDDEDEDITOR_MARGIN_LEFT 4
- #define EMBEDDEDEDITOR_MARGIN_TOP 1
- #define EMBEDDEDEDITOR_MARGIN_RIGHT 4
- #define EMBEDDEDEDITOR_MARGIN_BOTTOM 1
- #define EMBEDDEDEDITOR_BORDER_LEFT (EMBEDDEDEDITOR_FRAME_LEFT + \
- EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_LEFT + \
- EMBEDDEDEDITOR_FRAME_INNER_SPACE_LEFT)
- #define EMBEDDEDEDITOR_BORDER_TOP (EMBEDDEDEDITOR_FRAME_TOP + \
- EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_TOP + \
- EMBEDDEDEDITOR_FRAME_INNER_SPACE_TOP)
- #define EMBEDDEDEDITOR_BORDER_RIGHT (EMBEDDEDEDITOR_FRAME_RIGHT + \
- EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_RIGHT + \
- EMBEDDEDEDITOR_FRAME_INNER_SPACE_RIGHT)
- #define EMBEDDEDEDITOR_BORDER_BOTTOM (EMBEDDEDEDITOR_FRAME_BOTTOM + \
- EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_BOTTOM + \
- EMBEDDEDEDITOR_FRAME_INNER_SPACE_BOTTOM)
- typedef struct EmbeddedEditor
- {
- WNDPROC originalProc;
- COLORREF textColor;
- COLORREF backColor;
- COLORREF borderColor;
- HBRUSH backBrush;
- HBRUSH borderBrush;
- EmbeddedEditorFinishCb callback;
- void *user;
- POINT anchorPoint;
- SIZE maximumSize;
- wchar_t *buffer;
- size_t bufferSize;
- long spacing;
- long lineHeight;
- } EmbeddedEditor;
- typedef std::vector<HWND> WindowList;
- typedef struct EmbeddedEditorParent
- {
- WNDPROC originalProc;
- WindowList editorList;
- } EmbeddedEditorParent;
- typedef struct EmbeddedEditorThread
- {
- HHOOK hook;
- HWND window;
- } EmbeddedEditorThread;
- static size_t editorTls = ((size_t)-1);
- static ATOM EMBEDDEDEDITOR_PROP = 0;
- #define EMBEDDEDEDITOR(_hwnd) ((EmbeddedEditor*)GetPropW((_hwnd), MAKEINTATOM(EMBEDDEDEDITOR_PROP)))
- #define EMBEDDEDEDITOR_RET_VOID(_self, _hwnd) { (_self) = EMBEDDEDEDITOR((_hwnd)); if (NULL == (_self)) return; }
- #define EMBEDDEDEDITOR_RET_VAL(_self, _hwnd, _error) { (_self) = EMBEDDEDEDITOR((_hwnd)); if (NULL == (_self)) return (_error); }
- #define EMBEDDEDEDITOR_PARENT(_hwnd) ((EmbeddedEditorParent*)GetPropW((_hwnd), MAKEINTATOM(EMBEDDEDEDITOR_PROP)))
- static LRESULT WINAPI
- EmbeddedEditor_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
- static LRESULT WINAPI
- EmbeddedEditorParent_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
- static LRESULT CALLBACK
- EmbeddidEditorThread_MouseProc(int code, unsigned int messageId, MOUSEHOOKSTRUCT *mouse);
- static BOOL
- EmbeddidEditorThread_BeginMouseMonitor(HWND editorWindow)
- {
- EmbeddedEditorThread *threadData;
- if (NULL == WASABI_API_APP ||
- NULL == editorWindow)
- {
- return FALSE;
- }
-
- if ((size_t)-1 == editorTls)
- {
- editorTls = WASABI_API_APP->AllocateThreadStorage();
- if ((size_t)-1 == editorTls)
- return FALSE;
- threadData = NULL;
- }
- else
- {
- threadData = (EmbeddedEditorThread*)WASABI_API_APP->GetThreadStorage(editorTls);
- WASABI_API_APP->SetThreadStorage(editorTls, NULL);
- }
-
- if (NULL != threadData)
- {
- if (NULL != threadData->window)
- DestroyWindow(threadData->window);
- }
- else
- {
- threadData = (EmbeddedEditorThread*)malloc(sizeof(EmbeddedEditorThread));
- if (NULL == threadData)
- return FALSE;
- threadData->hook = SetWindowsHookEx(WH_MOUSE, (HOOKPROC)EmbeddidEditorThread_MouseProc, NULL, GetCurrentThreadId());
- if (NULL == threadData->hook)
- {
- free(threadData);
- return FALSE;
- }
- }
- threadData->window = editorWindow;
- WASABI_API_APP->SetThreadStorage(editorTls, threadData);
-
- return TRUE;
- }
- static void
- EmbeddidEditorThread_EndMouseMonitor(HWND editorWindow)
- {
- EmbeddedEditorThread *threadData;
- if (NULL == WASABI_API_APP ||
- (size_t)-1 == editorTls ||
- NULL == editorWindow)
- {
- return;
- }
-
- threadData = (EmbeddedEditorThread*)WASABI_API_APP->GetThreadStorage(editorTls);
- WASABI_API_APP->SetThreadStorage(editorTls, NULL);
-
- if (NULL != threadData)
- {
- if (NULL != threadData->hook)
- UnhookWindowsHookEx(threadData->hook);
- free(threadData);
- }
- }
- static BOOL
- EmbeddedEditorParent_AddChild(HWND hwnd, HWND child)
- {
- EmbeddedEditorParent *self;
- if (NULL == hwnd || NULL == child)
- return FALSE;
- self = EMBEDDEDEDITOR_PARENT(hwnd);
- if (NULL == self)
- {
- self = new EmbeddedEditorParent();
- if (NULL == self)
- return FALSE;
- self->originalProc = (WNDPROC)(LONG_PTR)SetWindowLongPtr(hwnd, GWLP_WNDPROC,
- (LONGX86)(LONG_PTR)EmbeddedEditorParent_WindowProc);
-
- if (NULL != self->originalProc &&
- FALSE == SetProp(hwnd, MAKEINTATOM(EMBEDDEDEDITOR_PROP), self))
- {
- SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)self->originalProc);
- delete self;
- return FALSE;
- }
- }
- else
- {
- size_t index;
- index = self->editorList.size();
- while(index--)
- {
- if (self->editorList[index] == child)
- return FALSE;
- }
- }
- self->editorList.push_back(child);
- return TRUE;
- }
- static BOOL
- EmbeddedEditorParent_RemoveChild(HWND hwnd, HWND child)
- {
- size_t index;
- EmbeddedEditorParent *self;
- if (NULL == hwnd || NULL == child)
- return FALSE;
- self = EMBEDDEDEDITOR_PARENT(hwnd);
- if (NULL == self)
- return FALSE;
- index = self->editorList.size();
- while(index--)
- {
- if (self->editorList[index] == child)
- break;
- }
- if (((size_t)-1) == index)
- return FALSE;
-
- self->editorList.erase(self->editorList.begin() + index);
- if (0 == self->editorList.size())
- {
- RemoveProp(hwnd, MAKEINTATOM(EMBEDDEDEDITOR_PROP));
- if (NULL != self->originalProc)
- SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)self->originalProc);
-
- delete self;
- }
- return TRUE;
- }
- BOOL
- EmbeddedEditor_Attach(HWND hwnd, EmbeddedEditorFinishCb callback, void *user)
- {
- HWND parent;
- EmbeddedEditor *self;
- if (NULL == hwnd)
- return FALSE;
- if (0 == EMBEDDEDEDITOR_PROP)
- {
- EMBEDDEDEDITOR_PROP = GlobalAddAtom(TEXT("EmdeddedEditorProp"));
- if (0 == EMBEDDEDEDITOR_PROP)
- return FALSE;
- }
-
- self = (EmbeddedEditor*)malloc(sizeof(EmbeddedEditor));
- if (NULL == self)
- return FALSE;
- memset(self, 0, sizeof(EmbeddedEditor));
- self->originalProc = (WNDPROC)(LONG_PTR)SetWindowLongPtr(hwnd, GWLP_WNDPROC,
- (LONGX86)(LONG_PTR)EmbeddedEditor_WindowProc);
-
- if (NULL != self->originalProc &&
- FALSE == SetProp(hwnd, MAKEINTATOM(EMBEDDEDEDITOR_PROP), self))
- {
- SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)self->originalProc);
- free(self);
- return FALSE;
- }
- self->callback = callback;
- self->user = user;
- self->backColor = RGB(0, 0, 255); //GetSysColor(COLOR_WINDOW);
- self->backBrush = NULL;
- self->textColor = RGB(255, 255, 0); //GetSysColor(COLOR_WINDOWTEXT);
- self->borderColor = RGB(255, 0, 0); //GetSysColor(COLOR_WINDOWFRAME);
- self->borderBrush = NULL;
- self->spacing = -1;
- self->lineHeight = -1;
- parent = GetAncestor(hwnd, GA_PARENT);
- if(NULL != parent)
- EmbeddedEditorParent_AddChild(parent, hwnd);
- EmbeddidEditorThread_BeginMouseMonitor(hwnd);
-
- RECT rect, formatRect;
- GetWindowRect(hwnd, &rect);
- SetRect(&formatRect, 0, 0, RECTWIDTH(rect) - 6, RECTHEIGHT(rect) - 6);
- SendMessage(hwnd, EM_SETRECTNP, 0, (LPARAM)&formatRect);
- SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
- SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED);
-
- return TRUE;
- }
- BOOL
- EmbeddedEditor_AdjustWindowRectEx(RECT *rect, unsigned long styleEx, unsigned long style)
- {
- if (NULL == rect)
- return FALSE;
- if (0 != ((WS_EX_STATICEDGE | WS_EX_CLIENTEDGE) & styleEx) ||
- 0 != (WS_BORDER & style))
- {
- rect->left -= (EMBEDDEDEDITOR_BORDER_LEFT + EMBEDDEDEDITOR_MARGIN_LEFT);
- rect->top -= (EMBEDDEDEDITOR_BORDER_TOP + EMBEDDEDEDITOR_MARGIN_TOP);
- rect->right += (EMBEDDEDEDITOR_BORDER_RIGHT + EMBEDDEDEDITOR_MARGIN_RIGHT);
- rect->bottom += (EMBEDDEDEDITOR_BORDER_BOTTOM + EMBEDDEDEDITOR_MARGIN_BOTTOM);
- }
-
- return TRUE;
- }
- static HBRUSH
- EmbeddedEditor_GetBackBrush(EmbeddedEditor *self)
- {
- if (NULL == self->backBrush)
- self->backBrush = CreateSolidBrush(self->backColor);
- return self->backBrush;
- }
- static HBRUSH
- EmbeddedEditor_GetBorderBrush(EmbeddedEditor *self)
- {
- if (NULL == self->borderBrush)
- self->borderBrush = CreateSolidBrush(self->borderColor);
- return self->borderBrush;
- }
- static BOOL
- EmbdeddedEditor_GetBorderEnabled(HWND hwnd)
- {
- unsigned long style;
-
- style = GetWindowStyleEx(hwnd);
- if (0 != ((WS_EX_STATICEDGE | WS_EX_CLIENTEDGE) & style))
- return TRUE;
- style = GetWindowStyle(hwnd);
- if (0 != (WS_BORDER & style))
- return TRUE;
- return FALSE;
- }
- static BOOL
- EmbdeddedEditor_DrawBorder(EmbeddedEditor *self, HWND hwnd, HDC hdc)
- {
- RECT windowRect, clientRect;
- HRGN borderRgn;
- POINT polygons[16] = {0};
- const int polygonsPointCount[] = {4, 4, 4, 4};
- if (FALSE == GetWindowRect(hwnd, &windowRect) ||
- FALSE == GetClientRect(hwnd, &clientRect))
- {
- return FALSE;
- }
- MapWindowPoints(hwnd, HWND_DESKTOP, (POINT*)&clientRect, 2);
- OffsetRect(&clientRect, -windowRect.left, -windowRect.top);
- OffsetRect(&windowRect, -windowRect.left, -windowRect.top);
- MakeRectPolygon(&polygons[0], windowRect.left, windowRect.top, windowRect.right, clientRect.top);
- MakeRectPolygon(&polygons[4], clientRect.right, clientRect.top, windowRect.right, clientRect.bottom);
- MakeRectPolygon(&polygons[8], windowRect.left, clientRect.bottom, windowRect.right, windowRect.bottom);
- MakeRectPolygon(&polygons[12], windowRect.left, clientRect.top, clientRect.left, clientRect.bottom);
-
- borderRgn = CreatePolyPolygonRgn(polygons,
- polygonsPointCount,
- ARRAYSIZE(polygonsPointCount),
- WINDING);
- if (NULL != borderRgn)
- {
- MakeRectPolygon(&polygons[0],
- windowRect.left + EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_LEFT,
- windowRect.top + EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_TOP,
- windowRect.right - EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_RIGHT,
- windowRect.top + (EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_TOP + EMBEDDEDEDITOR_FRAME_TOP));
- MakeRectPolygon(&polygons[4],
- windowRect.right - (EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_RIGHT + EMBEDDEDEDITOR_FRAME_RIGHT),
- windowRect.top + (EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_TOP + EMBEDDEDEDITOR_FRAME_TOP),
- windowRect.right - EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_RIGHT,
- windowRect.bottom - (EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_BOTTOM + EMBEDDEDEDITOR_FRAME_BOTTOM));
- MakeRectPolygon(&polygons[8],
- windowRect.left + EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_LEFT,
- windowRect.bottom - (EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_BOTTOM + EMBEDDEDEDITOR_FRAME_BOTTOM),
- windowRect.right - EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_RIGHT,
- windowRect.bottom - EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_BOTTOM);
- MakeRectPolygon(&polygons[12],
- windowRect.left + EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_LEFT,
- windowRect.top + (EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_TOP + EMBEDDEDEDITOR_FRAME_TOP),
- windowRect.left + (EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_LEFT + EMBEDDEDEDITOR_FRAME_LEFT),
- windowRect.bottom - (EMBEDDEDEDITOR_FRAME_OUTTER_SPACE_BOTTOM + EMBEDDEDEDITOR_FRAME_BOTTOM));
- HRGN frameRgn = CreatePolyPolygonRgn(polygons,
- polygonsPointCount,
- ARRAYSIZE(polygonsPointCount),
- WINDING);
- if (NULL != frameRgn)
- {
- int combineResult = CombineRgn(frameRgn, borderRgn, frameRgn, RGN_AND);
- if (NULLREGION != combineResult && ERROR != combineResult)
- {
- FillRgn(hdc, frameRgn, EmbeddedEditor_GetBorderBrush(self));
- combineResult = CombineRgn(borderRgn, borderRgn, frameRgn, RGN_DIFF);
- }
- else
- combineResult = COMPLEXREGION;
- if (NULLREGION != combineResult && ERROR != combineResult)
- FillRgn(hdc, borderRgn, EmbeddedEditor_GetBackBrush(self));
-
- DeleteObject(frameRgn);
- }
- DeleteObject(borderRgn);
- }
-
- return TRUE;
- }
- static BOOL
- EmbeddedEditor_InvokeCallback(EmbeddedEditor *self, HWND hwnd, BOOL cancelMode, BOOL removeCallback)
- {
- wchar_t *text;
- unsigned int length;
- EmbeddedEditorFinishCb callback;
- if (NULL == self || NULL == self->callback)
- return FALSE;
-
-
- length = (unsigned int)SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0L);
- text = String_Malloc(++length);
- if (NULL == text)
- return FALSE;
-
- SendMessage(hwnd, WM_GETTEXT, (WPARAM)length, (LPARAM)text);
- callback = self->callback;
- if (FALSE != removeCallback)
- self->callback = NULL;
- callback(hwnd, cancelMode, text, self->user);
-
- return TRUE;
- }
- static const wchar_t *
- EmbeddedEditor_GetWindowText(EmbeddedEditor *self, HWND hwnd, size_t *lengthOut)
- {
- size_t length;
- length = (size_t)SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0L);
- if (length >= self->bufferSize)
- {
- size_t size;
- size = (((length + 1)/128) + 1) * 128;
- String_Free(self->buffer);
- self->buffer = String_Malloc(size);
- if (NULL == self->buffer)
- return FALSE;
- self->bufferSize = size;
- }
- if (0 != length)
- length = SendMessage(hwnd, WM_GETTEXT, (WPARAM)self->bufferSize, (LPARAM)self->buffer);
- else
- self->buffer[0] = L'\0';
- if (NULL != lengthOut)
- *lengthOut = length;
- return self->buffer;
- }
- static BOOL
- EmbeddedEditor_Resize(EmbeddedEditor *self, HWND hwnd, BOOL redraw)
- {
- size_t textLength;
- const wchar_t *text;
- HDC hdc;
- SIZE maximumSize;
- BOOL borderEnabled;
- HWND parentWindow;
- RECT rect, parentRect, marginRect;
- SIZE parentSize;
- BOOL result;
- unsigned int windowStyle;
- HFONT font, prevFont;
- parentWindow = GetAncestor(hwnd, GA_PARENT);
- if (NULL == parentWindow ||
- FALSE == GetClientRect(parentWindow, &parentRect))
- {
- return FALSE;
- }
- parentSize.cx = RECTWIDTH(parentRect);
- parentSize.cy = RECTHEIGHT(parentRect);
- windowStyle = GetWindowStyle(hwnd);
- borderEnabled = EmbdeddedEditor_GetBorderEnabled(hwnd);
- text = EmbeddedEditor_GetWindowText(self, hwnd, &textLength);
- if (NULL == text)
- return FALSE;
-
- hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
- if (NULL == hdc)
- return FALSE;
- result = FALSE;
- font = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0L);
- prevFont = SelectFont(hdc, font);
- if (-1 == self->spacing ||
- -1 == self->lineHeight)
- {
- TEXTMETRIC textMetrics;
- if (FALSE != GetTextMetrics(hdc, &textMetrics))
- {
- self->spacing = textMetrics.tmAveCharWidth;
- self->lineHeight = textMetrics.tmHeight;
- }
- }
- if (0 == (ES_MULTILINE & windowStyle))
- {
- unsigned long margins;
- margins = (unsigned long)SendMessage(hwnd, EM_GETMARGINS, 0, 0L);
- SetRect(&marginRect, (short)LOWORD(margins), 0, (short)HIWORD(margins), 0);
- }
- else
- {
- RECT clientRect;
- if (FALSE == GetClientRect(hwnd, &clientRect))
- SetRectEmpty(&clientRect);
-
- if (clientRect.right < clientRect.left)
- clientRect.right = clientRect.left;
- if (clientRect.bottom < (clientRect.top + self->lineHeight))
- clientRect.bottom = clientRect.top + self->lineHeight;
- SendMessage(hwnd, EM_GETRECT, 0, (LPARAM)&marginRect);
-
- marginRect.left = (marginRect.left > clientRect.left) ?
- (marginRect.left - clientRect.left) : 1;
- marginRect.top = (marginRect.top > clientRect.top) ?
- (marginRect.top - clientRect.top) : 1;
- marginRect.right = (marginRect.right < clientRect.right) ?
- (clientRect.right - marginRect.right) : 1;
- marginRect.bottom = (marginRect.bottom < clientRect.bottom) ?
- (clientRect.bottom - marginRect.bottom) : 1;
- if (SendMessage(hwnd, EM_GETLINECOUNT, 0, 0L) > 1)
- {
- if (marginRect.bottom >= (self->lineHeight - 1))
- marginRect.bottom -= (self->lineHeight - 2);
- }
- SetRect(&marginRect, EMBEDDEDEDITOR_MARGIN_LEFT, EMBEDDEDEDITOR_MARGIN_TOP,
- EMBEDDEDEDITOR_MARGIN_RIGHT, EMBEDDEDEDITOR_MARGIN_BOTTOM);
- }
-
- maximumSize.cx = (self->maximumSize.cx > 0) ? MIN(parentSize.cx, self->maximumSize.cx) : parentSize.cx;
- maximumSize.cx -= (marginRect.left + marginRect.right);
- if (FALSE != borderEnabled)
- maximumSize.cx -= (EMBEDDEDEDITOR_BORDER_LEFT + EMBEDDEDEDITOR_BORDER_RIGHT);
- if (maximumSize.cx < 0)
- maximumSize.cx = 0;
- maximumSize.cy = (self->maximumSize.cy > 0) ? MIN(parentSize.cy, self->maximumSize.cy) : parentSize.cy;
- maximumSize.cy -= (marginRect.top + marginRect.bottom);
- if (FALSE != borderEnabled)
- maximumSize.cy -= (EMBEDDEDEDITOR_BORDER_TOP + EMBEDDEDEDITOR_BORDER_BOTTOM);
- if (maximumSize.cy < 0)
- maximumSize.cy = 0;
-
- if (0 == textLength)
- {
- SetRectEmpty(&rect);
- result = TRUE;
- }
- else
- {
- SetRect(&rect, 0, 0, maximumSize.cx, maximumSize.cy);
- result = DrawText(hdc, text, (int)textLength, &rect,
- DT_CALCRECT | DT_LEFT | DT_TOP | DT_WORDBREAK |
- DT_EDITCONTROL | DT_NOPREFIX);
- }
- SelectFont(hdc, prevFont);
- ReleaseDC(hwnd, hdc);
- if (FALSE != result)
- {
- unsigned int flags;
-
- rect.right += 2 * self->spacing;
- if (RECTHEIGHT(rect) < self->lineHeight)
- rect.bottom = rect.top + self->lineHeight;
- else if (RECTHEIGHT(rect) > self->lineHeight)
- rect.right = rect.left + maximumSize.cx;
- rect.right += (marginRect.left + marginRect.right);
- rect.bottom += (marginRect.top + marginRect.bottom);
-
- if (FALSE != borderEnabled)
- {
- rect.right += (EMBEDDEDEDITOR_BORDER_LEFT + EMBEDDEDEDITOR_BORDER_RIGHT);
- rect.bottom += (EMBEDDEDEDITOR_BORDER_TOP + EMBEDDEDEDITOR_BORDER_BOTTOM);
- }
- flags = SWP_NOACTIVATE | SWP_NOZORDER;
- if (FALSE == redraw)
- flags |= SWP_NOREDRAW;
-
- OffsetRect(&rect, self->anchorPoint.x, self->anchorPoint.y);
- long offsetX = 0, offsetY = 0;
- if (0 != (ES_CENTER & windowStyle))
- {
- if (self->maximumSize.cx > 0)
- {
- offsetX += (self->maximumSize.cx - RECTWIDTH(rect))/2;
- }
- }
-
- if (rect.right > parentSize.cx)
- offsetX -= (rect.right - parentSize.cx);
- if (rect.bottom > parentSize.cy)
- offsetY -= (rect.bottom - parentSize.cy);
- OffsetRect(&rect, offsetX, offsetY);
- result = SetWindowPos(hwnd, NULL, rect.left, rect.top, RECTWIDTH(rect), RECTHEIGHT(rect), flags);
- }
-
- return result;
- }
- static void
- EmbdeddedEditor_OnDestroy(EmbeddedEditor *self, HWND hwnd)
- {
- HWND parent;
- if (NULL != self &&
- NULL != self->callback)
- {
- EmbeddedEditor_InvokeCallback(self, hwnd, TRUE, TRUE);
- }
- RemoveProp(hwnd, MAKEINTATOM(EMBEDDEDEDITOR_PROP));
- if (NULL == self)
- return;
- if (NULL != self->originalProc)
- {
- SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)self->originalProc);
- CallWindowProc(self->originalProc, hwnd, WM_DESTROY, 0, 0L);
- }
- if(NULL != self->backBrush)
- DeleteObject(self->backBrush);
- if (NULL != self->borderBrush)
- DeleteObject(self->borderBrush);
- String_Free(self->buffer);
- free(self);
- parent = GetAncestor(hwnd, GA_PARENT);
- if(NULL != parent)
- EmbeddedEditorParent_RemoveChild(parent, hwnd);
- EmbeddidEditorThread_EndMouseMonitor(hwnd);
- }
- static BOOL
- EmbdeddedEditor_OnNcCalcSize(EmbeddedEditor *self, HWND hwnd, BOOL calcValidRects,
- NCCALCSIZE_PARAMS *params, LRESULT *result)
- {
- if (FALSE != EmbdeddedEditor_GetBorderEnabled(hwnd))
- {
- if (FALSE != calcValidRects)
- {
- SetRect(¶ms->rgrc[0],
- params->lppos->x + EMBEDDEDEDITOR_BORDER_LEFT,
- params->lppos->y + EMBEDDEDEDITOR_BORDER_TOP,
- params->lppos->x + params->lppos->cx - EMBEDDEDEDITOR_BORDER_RIGHT,
- params->lppos->y + params->lppos->cy - EMBEDDEDEDITOR_BORDER_BOTTOM);
- *result = WVR_ALIGNTOP | WVR_ALIGNLEFT;
- }
- else
- {
- if (FALSE != GetWindowRect(hwnd, ¶ms->rgrc[0]))
- {
- params->rgrc[0].left += EMBEDDEDEDITOR_BORDER_LEFT;
- params->rgrc[0].top += EMBEDDEDEDITOR_BORDER_TOP;
- params->rgrc[0].right -= EMBEDDEDEDITOR_BORDER_RIGHT;
- params->rgrc[0].bottom -= EMBEDDEDEDITOR_BORDER_BOTTOM;
- }
- }
- }
- return TRUE;
- }
- static BOOL
- EmbdeddedEditor_OnNcPaint(EmbeddedEditor *self, HWND hwnd, HRGN updateRegion)
- {
- BOOL result;
- if (FALSE != EmbdeddedEditor_GetBorderEnabled(hwnd))
- {
- HDC hdc;
- unsigned int flags;
- flags = DCX_PARENTCLIP | DCX_CACHE | DCX_WINDOW | DCX_CLIPSIBLINGS |
- DCX_INTERSECTUPDATE | DCX_VALIDATE;
- hdc = GetDCEx(hwnd, ((HRGN)NULLREGION != updateRegion) ? updateRegion : NULL, flags);
- if (NULL != hdc)
- {
- result = EmbdeddedEditor_DrawBorder(self, hwnd, hdc);
- ReleaseDC(hwnd, hdc);
- }
- else
- result = FALSE;
- }
- else
- result = TRUE;
-
- return result;
- }
- static BOOL
- EmbeddedEditor_OnSetCursor(EmbeddedEditor *self, HWND hwnd, HWND cursorWindow, int hitTest, int mouseMessage, LRESULT *result)
- {
- HCURSOR cursor;
- if (cursorWindow != hwnd ||
- HTCLIENT != hitTest)
- {
- return FALSE;
- }
- cursor = LoadCursor(NULL, IDC_IBEAM);
- if (NULL == cursor)
- return FALSE;
- SetCursor(cursor);
- *result = TRUE;
- return TRUE;
- }
- static BOOL
- EmbeddedEditor_OnGetDlgCode(EmbeddedEditor *self, HWND hwnd, unsigned int vKey, MSG *message, LRESULT *result)
- {
- if (NULL != message)
- {
- switch(vKey)
- {
- case VK_TAB:
- case VK_ESCAPE:
- EmbeddedEditor_InvokeCallback(self, hwnd, TRUE, TRUE);
- DestroyWindow(hwnd);
- *result = DLGC_WANTMESSAGE;
- return TRUE;
- case VK_RETURN:
- EmbeddedEditor_InvokeCallback(self, hwnd, FALSE, TRUE);
- DestroyWindow(hwnd);
- *result = DLGC_WANTMESSAGE;
- return TRUE;
- }
- }
- if (NULL != self->originalProc)
- *result = CallWindowProc(self->originalProc, hwnd, WM_GETDLGCODE, (WPARAM)vKey, (LPARAM)message);
- else
- *result = 0;
- if (NULL == message)
- *result |= DLGC_WANTMESSAGE;
- return TRUE;
- }
- static BOOL
- EmbeddedEditor_OnKillFocus(EmbeddedEditor *self, HWND hwnd, HWND focusedWindow)
- {
- EmbeddedEditor_InvokeCallback(self, hwnd, FALSE, TRUE);
- DestroyWindow(hwnd);
- return TRUE;
- }
- static BOOL
- EmbeddedEditor_OnMouseWheel(EmbeddedEditor *self, HWND hwnd, int virtualKeys, int distance, long pointer_s)
- {
- HWND parentWindow;
- parentWindow = GetAncestor(hwnd, GA_PARENT);
- EmbeddedEditor_InvokeCallback(self, hwnd, TRUE, TRUE);
- DestroyWindow(hwnd);
-
- if (NULL != parentWindow)
- {
- SendMessage(parentWindow, WM_MOUSEWHEEL,
- MAKEWPARAM(virtualKeys, distance), (LPARAM)pointer_s);
- }
- return TRUE;
- }
- static void
- EmbeddedEditor_OnCommand(EmbeddedEditor *self, HWND hwnd, int eventId)
- {
- switch(eventId)
- {
- case EN_UPDATE:
- EmbeddedEditor_Resize(self, hwnd, TRUE);
- break;
- }
- }
- static BOOL
- EmbeddedEditor_OnSetFont(EmbeddedEditor *self, HWND hwnd, HFONT font, BOOL redraw)
- {
- if (NULL != self->originalProc)
- CallWindowProc(self->originalProc, hwnd, WM_SETFONT, (WPARAM)font, MAKELPARAM(redraw, 0));
- self->spacing = -1;
- self->lineHeight = -1;
- EmbeddedEditor_Resize(self, hwnd, redraw);
- return TRUE;
- }
- static BOOL
- EmbeddedEditor_OnWindowPosChanged(EmbeddedEditor *self, HWND hwnd, WINDOWPOS *pwp)
- {
- if (SWP_NOSIZE != ((SWP_NOSIZE | SWP_FRAMECHANGED) & pwp->flags))
- {
- RECT formatRect;
- if (FALSE != GetClientRect(hwnd, &formatRect))
- {
- formatRect.left += EMBEDDEDEDITOR_MARGIN_LEFT;
- formatRect.top += EMBEDDEDEDITOR_MARGIN_TOP;
- formatRect.right -= EMBEDDEDEDITOR_MARGIN_RIGHT;
- formatRect.bottom -= EMBEDDEDEDITOR_MARGIN_BOTTOM;
-
- if (formatRect.right < formatRect.left)
- formatRect.right = formatRect.left;
- if (formatRect.bottom < formatRect.top)
- formatRect.bottom = formatRect.top;
- SendMessage(hwnd, EM_SETRECTNP, 0, (LPARAM)&formatRect);
- }
- }
- if (NULL != self->originalProc)
- CallWindowProc(self->originalProc, hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)pwp);
- return TRUE;
- }
- static void
- EmbeddedEditor_OnSetTextColor(EmbeddedEditor *self, HWND hwnd, COLORREF color, LRESULT *result)
- {
- *result = (LRESULT)self->textColor;
- if (self->textColor != color)
- self->textColor = color;
- }
- static void
- EmbeddedEditor_OnGetTextColor(EmbeddedEditor *self, HWND hwnd, LRESULT *result)
- {
- *result = (LRESULT)self->textColor;
- }
- static void
- EmbeddedEditor_OnSetBackColor(EmbeddedEditor *self, HWND hwnd, COLORREF color, LRESULT *result)
- {
- *result = (LRESULT)self->backColor;
- if (self->backColor != color)
- {
- self->backColor = color;
- if (NULL != self->backBrush)
- {
- DeleteObject(self->backBrush);
- self->backBrush = NULL;
- }
- }
- }
- static void
- EmbeddedEditor_OnGetBackColor(EmbeddedEditor *self, HWND hwnd, LRESULT *result)
- {
- *result = (LRESULT)self->backColor;
- }
- static void
- EmbeddedEditor_OnSetBorderColor(EmbeddedEditor *self, HWND hwnd, COLORREF color, LRESULT *result)
- {
- *result = (LRESULT)self->borderColor;
- if (self->borderColor != color)
- {
- self->borderColor = color;
- if (NULL != self->borderBrush)
- {
- DeleteObject(self->borderBrush);
- self->borderBrush = NULL;
- }
- }
- }
- static void
- EmbeddedEditor_OnGetBorderColor(EmbeddedEditor *self, HWND hwnd, LRESULT *result)
- {
- *result = (LRESULT)self->borderColor;
- }
- static void
- EmbeddedEditor_OnSetUserData(EmbeddedEditor *self, HWND hwnd, void *user, LRESULT *result)
- {
- *result = (LRESULT)self->user;
- self->user = user;
- }
- static void
- EmbeddedEditor_OnGetUserData(EmbeddedEditor *self, HWND hwnd, LRESULT *result)
- {
- *result = (LRESULT)self->user;
- }
- static void
- EmbeddedEditor_OnSetAnchorPoint(EmbeddedEditor *self, HWND hwnd, long x, long y, LRESULT *result)
- {
- self->anchorPoint.x = x;
- self->anchorPoint.y = y;
- *result = TRUE;
- }
- static void
- EmbeddedEditor_OnGetAnchorPoint(EmbeddedEditor *self, HWND hwnd, long *x, long *y, LRESULT *result)
- {
- if (NULL != x)
- *x = self->anchorPoint.x;
- if (NULL != y)
- *y = self->anchorPoint.y;
-
- *result = TRUE;
- }
- static void
- EmbeddedEditor_OnSetMaxSize(EmbeddedEditor *self, HWND hwnd, long width, long height, LRESULT *result)
- {
- self->maximumSize.cx = width;
- self->maximumSize.cy = height;
- *result = TRUE;
- }
- static void
- EmbeddedEditor_OnGetMaxSize(EmbeddedEditor *self, HWND hwnd, long *width, long *height, LRESULT *result)
- {
- if (NULL != width)
- *width = self->maximumSize.cx;
- if (NULL != height)
- *height = self->maximumSize.cy;
-
- *result = TRUE;
- }
- static void
- EmbeddedEditor_OnEndEditing(EmbeddedEditor *self, HWND hwnd, BOOL cancel)
- {
- EmbeddedEditor_InvokeCallback(self, hwnd, cancel, TRUE);
- DestroyWindow(hwnd);
- }
- static BOOL
- EmbeddedEditor_MessageProc(EmbeddedEditor *self, HWND hwnd, UINT uMsg,
- WPARAM wParam, LPARAM lParam, LRESULT *result)
- {
- switch(uMsg)
- {
- case WM_DESTROY:
- EmbdeddedEditor_OnDestroy(self, hwnd);
- return TRUE;
- case WM_NCCALCSIZE:
- return EmbdeddedEditor_OnNcCalcSize(self, hwnd, (BOOL)wParam, (NCCALCSIZE_PARAMS*)lParam, result);
- case WM_NCPAINT:
- return EmbdeddedEditor_OnNcPaint(self, hwnd, (HRGN)wParam);
- case WM_SETCURSOR:
- return EmbeddedEditor_OnSetCursor(self, hwnd, (HWND)wParam,
- LOWORD(lParam), HIWORD(lParam), result);
- case WM_GETDLGCODE:
- return EmbeddedEditor_OnGetDlgCode(self, hwnd, (unsigned int)wParam, (MSG*)lParam, result);
- case WM_KILLFOCUS:
- EmbeddedEditor_OnKillFocus(self, hwnd, (HWND)wParam);
- return 0;
- case WM_MOUSEWHEEL:
- return EmbeddedEditor_OnMouseWheel(self, hwnd, LOWORD(wParam), (short)HIWORD(wParam), (LONG)lParam);
- case WM_SETFONT:
- return EmbeddedEditor_OnSetFont(self, hwnd, (HFONT)wParam, (BOOL)LOWORD(lParam));
- case WM_WINDOWPOSCHANGED:
- return EmbeddedEditor_OnWindowPosChanged(self, hwnd, (WINDOWPOS*)lParam);
- case EMBEDDEDEDITOR_WM_SET_TEXT_COLOR: EmbeddedEditor_OnSetTextColor(self, hwnd, (COLORREF)lParam, result); return TRUE;
- case EMBEDDEDEDITOR_WM_GET_TEXT_COLOR: EmbeddedEditor_OnGetTextColor(self, hwnd, result); return TRUE;
- case EMBEDDEDEDITOR_WM_SET_BACK_COLOR: EmbeddedEditor_OnSetBackColor(self, hwnd, (COLORREF)lParam, result); return TRUE;
- case EMBEDDEDEDITOR_WM_GET_BACK_COLOR: EmbeddedEditor_OnGetBackColor(self, hwnd, result); return TRUE;
- case EMBEDDEDEDITOR_WM_SET_BORDER_COLOR: EmbeddedEditor_OnSetBorderColor(self, hwnd, (COLORREF)lParam, result); return TRUE;
- case EMBEDDEDEDITOR_WM_GET_BORDER_COLOR: EmbeddedEditor_OnGetBorderColor(self, hwnd, result); return TRUE;
- case EMBEDDEDEDITOR_WM_SET_USER_DATA: EmbeddedEditor_OnSetUserData(self, hwnd, (void*)lParam, result); return TRUE;
- case EMBEDDEDEDITOR_WM_GET_USER_DATA: EmbeddedEditor_OnGetUserData(self, hwnd, result); return TRUE;
- case EMBEDDEDEDITOR_WM_SET_ANCHOR_POINT: EmbeddedEditor_OnSetAnchorPoint(self, hwnd, (long)wParam, (long)lParam, result); return TRUE;
- case EMBEDDEDEDITOR_WM_GET_ANCHOR_POINT: EmbeddedEditor_OnGetAnchorPoint(self, hwnd, (long*)wParam, (long*)lParam, result); return TRUE;
- case EMBEDDEDEDITOR_WM_SET_MAX_SIZE: EmbeddedEditor_OnSetMaxSize(self, hwnd, (long)wParam, (long)lParam, result); return TRUE;
- case EMBEDDEDEDITOR_WM_GET_MAX_SIZE: EmbeddedEditor_OnGetMaxSize(self, hwnd, (long*)wParam, (long*)lParam, result); return TRUE;
- case EMBEDDEDEDITOR_WM_END_EDITING: EmbeddedEditor_OnEndEditing(self, hwnd, (BOOL)wParam); return TRUE;
- }
- return FALSE;
- }
- static LRESULT WINAPI
- EmbeddedEditor_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- EmbeddedEditor *self;
- LRESULT result;
- self = EMBEDDEDEDITOR(hwnd);
- if (NULL == self ||
- NULL == self->originalProc)
- {
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
- }
- result = 0;
- if (FALSE != EmbeddedEditor_MessageProc(self, hwnd, uMsg, wParam, lParam, &result))
- {
- return result;
- }
- return CallWindowProc(self->originalProc, hwnd, uMsg, wParam, lParam);
- }
- static void
- EmbdeddedEditorParent_OnDestroy(EmbeddedEditorParent *self, HWND hwnd)
- {
- RemoveProp(hwnd, MAKEINTATOM(EMBEDDEDEDITOR_PROP));
- if (NULL == self)
- return;
- if (NULL != self->originalProc)
- {
- SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)self->originalProc);
- CallWindowProc(self->originalProc, hwnd, WM_DESTROY, 0, 0L);
- }
- delete self;
- }
- static BOOL
- EmbdeddedEditorParent_OnGetEditColors(EmbeddedEditorParent *self, HWND hwnd, HDC hdc, HWND control, LRESULT *result)
- {
- size_t index;
- index = self->editorList.size();
- while(index--)
- {
- if (control == self->editorList[index])
- {
- EmbeddedEditor *editor = EMBEDDEDEDITOR(control);
- if (NULL != editor)
- {
- SetTextColor(hdc, editor->textColor);
- SetBkColor(hdc, editor->backColor);
- *result = (LRESULT)EmbeddedEditor_GetBackBrush(editor);
- return TRUE;
- }
- }
- }
- return FALSE;
- }
- static void
- EmbdeddedEditorParent_OnCommand(EmbeddedEditorParent *self, HWND hwnd, int commandId, int eventId, HWND control)
- {
- size_t index;
- if (NULL == control)
- return;
- index = self->editorList.size();
- while(index--)
- {
- if (control == self->editorList[index])
- {
- EmbeddedEditor *editor = EMBEDDEDEDITOR(control);
- if (NULL != editor)
- {
- EmbeddedEditor_OnCommand(editor, control, eventId);
- }
- }
- }
- }
- static BOOL
- EmbeddedEditorParent_MessageProc(EmbeddedEditorParent *self, HWND hwnd, UINT uMsg,
- WPARAM wParam, LPARAM lParam, LRESULT *result)
- {
- switch(uMsg)
- {
- case WM_DESTROY:
- EmbdeddedEditorParent_OnDestroy(self, hwnd);
- return TRUE;
- case WM_CTLCOLOREDIT:
- return EmbdeddedEditorParent_OnGetEditColors(self, hwnd, (HDC)wParam, (HWND)lParam, result);
- case WM_COMMAND:
- EmbdeddedEditorParent_OnCommand(self, hwnd, LOWORD(wParam), HIWORD(wParam), (HWND)lParam);
- break;
- }
- return FALSE;
- }
- static LRESULT WINAPI
- EmbeddedEditorParent_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- EmbeddedEditorParent *self;
- LRESULT result;
- self = EMBEDDEDEDITOR_PARENT(hwnd);
- if (NULL == self ||
- NULL == self->originalProc)
- {
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
- }
- result = 0;
- if (FALSE != EmbeddedEditorParent_MessageProc(self, hwnd, uMsg, wParam, lParam, &result))
- {
- return result;
- }
- return CallWindowProc(self->originalProc, hwnd, uMsg, wParam, lParam);
- }
- static LRESULT CALLBACK
- EmbeddidEditorThread_MouseProc(int code, unsigned int messageId, MOUSEHOOKSTRUCT *mouse)
- {
- if ((size_t)-1 != editorTls)
- {
- EmbeddedEditorThread *threadData;
- threadData = (EmbeddedEditorThread*)WASABI_API_APP->GetThreadStorage(editorTls);
- if (NULL != threadData)
- {
- LRESULT result;
- if (NULL != threadData->hook)
- result = CallNextHookEx(threadData->hook, code, (WPARAM)messageId, (LPARAM)mouse);
- else
- result = 0;
- if (code >= 0)
- {
- if ((messageId >= WM_LBUTTONDOWN && messageId <= 0x20E && mouse->hwnd != threadData->window) ||
- (messageId >= WM_NCLBUTTONDOWN && messageId <= 0x00AD))
- {
-
- HWND editorWindow;
- editorWindow = threadData->window;
- if (NULL != editorWindow)
- PostMessage(editorWindow, EMBEDDEDEDITOR_WM_END_EDITING, FALSE, 0L);
- }
- }
-
- return result;
- }
- }
- return 0;
- }
|