/* Copyright (C) 1999, 2000 Guido Masarotto Copyright (C) 2004, The R Foundation Copyright (C) 2004-2022 The R Core Team Generalized version of widgets in buttons.c This file is part of GraphApp, a cross-platform C graphics library. GraphApp is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License. GraphApp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. See the file COPYLIB.TXT for details. */ #include "internal.h" /* Win32 style scrollbars */ void gchangescrollbar(scrollbar obj, int which, int where, int max, int pagesize, int disablenoscroll) { HWND hwnd; SCROLLINFO si; if (! obj) return; hwnd = obj->handle; switch (which) { case HWINSB: obj->xmax = max; obj->xsize = pagesize; which = SB_HORZ; break; case VWINSB: obj->max = max; obj->size = pagesize; which = SB_VERT; break; default: obj->max = max; obj->size = pagesize; which = SB_CTL; break; } si.cbSize = sizeof(si); si.fMask = disablenoscroll ? (SIF_ALL | SIF_DISABLENOSCROLL) : SIF_ALL; si.nMin = 0; si.nMax = max; si.nPage = pagesize; si.nPos = where; SetScrollInfo(hwnd, which, &si, 1); } void gsetcursor(drawing d, cursor c) { POINT pt; decrease_refcount(d->drawstate->crsr); d->drawstate->crsr = c; increase_refcount(c); /* ensure new cursor is shown */ GetCursorPos(&pt); SetCursorPos(pt.x, pt.y); } control newtoolbar(int height) { window c = current_window; if (!ismdi() || !c || (c==MDIFrame)) return NULL; addto(MDIFrame); c->toolbar = newwindow("TOOLBAR", rect(0, 0, 100, height), ChildWindow | Border); if (c->toolbar) { DWORD wcol = GetSysColor(COLOR_MENU); hide(c->toolbar); setbackground(c->toolbar, rgb( (wcol >> 0) & 0x000000FFL, (wcol >> 8) & 0x000000FFL, (wcol >> 16) & 0x000000FFL)); } addto(c); return (control) c->toolbar; } /* Fix background color for image on the toolbar. Designed to work with image in stdimc.c: (a) background is pixel (0,0); (b) image depth is 8 bits; (c) image is changed not copied. */ button newtoolbutton(image img, rect r, actionfn fn) { DWORD wcol = GetSysColor(COLOR_MENU); rgb col = rgb( (wcol >> 0) & 0x000000FFL, (wcol >> 8) & 0x000000FFL, (wcol >> 16) & 0x000000FFL); img->cmap[img->pixels[0]] = col; return newimagebutton(img, r, fn); } void scrolltext(textbox c, int lines) { int linecount = (INT) sendmessage(c->handle, EM_GETLINECOUNT, 0, 0); sendmessage(c->handle, EM_LINESCROLL, 0, linecount - lines); } int ggetkeystate(void) { int k = 0; if (GetKeyState(VK_CONTROL)&0x8000) k |= CtrlKey; if (GetKeyState(VK_MENU)&0x8000) k |= AltKey; if (GetKeyState(VK_SHIFT)&0x8000) k |= ShiftKey; return k; } /* Extra text editing functions for R, Chris Jackson */ #include /* Move the editor caret position lines down. If lines is negative moves caret up. Stops at the top or the bottom if lines is too big or small. */ void scrollcaret(textbox t, int lines) { long currentline, charindex; int linecount = (INT) sendmessage(t->handle, EM_GETLINECOUNT, 0, 0); currentline = (INT) sendmessage(t->handle, EM_LINEFROMCHAR, -1, 0); lines = (currentline + lines > linecount - 1 ? linecount - currentline - 1 : lines); lines = (currentline + lines < 0 ? - currentline : lines); charindex = (INT) sendmessage(t->handle, EM_LINEINDEX, currentline + lines, 0); sendmessage(t->handle, EM_SETSEL, charindex, charindex); } /* Modification flags for the text editor */ void gsetmodified(textbox t, int modified) { sendmessage(t->handle, EM_SETMODIFY, (WPARAM) modified, 0); } int ggetmodified(textbox t) { return (INT) sendmessage(t->handle, EM_GETMODIFY, 0, 0); } /* Get the length of the current line in an editing control */ int getlinelength(textbox t) { long charindex = (INT) sendmessage(t->handle, EM_LINEINDEX, -1, 0); return (INT) sendmessage(t->handle, EM_LINELENGTH, charindex, 0); } /* Copy the current line in the editor to a buffer */ void getcurrentline(textbox t, char *line, int length) { long currentline = (INT) sendmessage(t->handle, EM_LINEFROMCHAR, -1, 0); /* set first word of buffer to line length in TCHARs as required by EM_GETLINE */ WORD blength = length*MB_CUR_MAX + 1 + sizeof(WORD); *((LPWORD) line) = blength; sendmessage(t->handle, EM_GETLINE, currentline, line); line[blength - 1] = '\0'; } /* Copy the current selection in the editor to a buffer */ void getseltext(textbox t, char *text) { sendmessage(t->handle, EM_GETSELTEXT, 0, text); } /* Change the maximum number of characters (in bytes) allowed in an editor */ void setlimittext(textbox t, long limit) { sendmessage(t->handle, EM_EXLIMITTEXT, 0, limit); } long getlimittext(textbox t) { return (INT) sendmessage(t->handle, EM_GETLIMITTEXT, 0, 0); } /* Test whether the text limit needs to be increased to accommodate some new text of length n. If so increase it by required amount plus 32K. */ void checklimittext(textbox t, long n) { long limit = getlimittext(t); long len = GetWindowTextLength(t->handle); if (len + n >= limit) setlimittext(t, len + n + 0x8000); } /* Length of text in the clipboard */ long getpastelength(void) { HGLOBAL hglb; char *text; long pastelen; if ( OpenClipboard(NULL) && (hglb = GetClipboardData(CF_TEXT)) && (text = (char *)GlobalLock(hglb))) { pastelen = strlen(text); GlobalUnlock(hglb); CloseClipboard(); } else pastelen = 0; return pastelen; } /* Modification of the text selection functions in buttons.c to work with the EX messages used in rich edit controls. The selection messages without EX cannot handle more than 64K of text */ void textselectionex(control obj, long *start, long *end) { CHARRANGE sel; if (! obj) return; if ((obj->kind != FieldObject) && (obj->kind != TextboxObject)) return; sendmessage(obj->handle, EM_EXGETSEL, 0, &sel); *start = sel.cpMin; *end = sel.cpMax; } void selecttextex(control obj, long start, long end) { CHARRANGE sel; long length; if (! obj) return; if ((obj->kind != FieldObject) && (obj->kind != TextboxObject)) return; length = GetWindowTextLength(obj->handle); sel.cpMin = (start < 0) ? length : start; sel.cpMax = (end < 0) ? length : end; sendmessage(obj->handle, EM_EXSETSEL, 0, &sel); }