1 /* Copyright (C) 1999, 2000 Guido Masarotto
2    Copyright (C) 2004, The R Foundation
3 
4    Generalized version of widgets in buttons.c
5 
6 
7    This file is part of GraphApp, a cross-platform C graphics library.
8 
9    GraphApp is free software; you can redistribute it and/or modify it
10    under the terms of the GNU Library General Public License.
11    GraphApp is distributed in the hope that it will be useful, but
12    WITHOUT ANY WARRANTY.
13 
14    See the file COPYLIB.TXT for details.
15 */
16 
17 #include "internal.h"
18 
19 /* Win32 style scrollbars */
20 void
gchangescrollbar(scrollbar obj,int which,int where,int max,int pagesize,int disablenoscroll)21 gchangescrollbar(scrollbar obj, int which, int where, int max, int pagesize,
22 		 int disablenoscroll)
23 {
24     HWND hwnd;
25     SCROLLINFO si;
26 
27     if (! obj) return;
28     hwnd = obj->handle;
29     switch (which) {
30     case HWINSB:
31 	obj->xmax = max;
32 	obj->xsize = pagesize;
33 	which = SB_HORZ;
34 	break;
35     case VWINSB:
36 	obj->max = max;
37 	obj->size = pagesize;
38 	which = SB_VERT;
39 	break;
40     default:
41 	obj->max = max;
42 	obj->size = pagesize;
43 	which = SB_CTL;
44 	break;
45     }
46     si.cbSize = sizeof(si);
47     si.fMask  = disablenoscroll ? (SIF_ALL | SIF_DISABLENOSCROLL) : SIF_ALL;
48     si.nMin   = 0;
49     si.nMax   = max;
50     si.nPage  = pagesize;
51     si.nPos   = where;
52     SetScrollInfo(hwnd, which, &si, 1);
53 }
54 
gsetcursor(drawing d,cursor c)55 void gsetcursor(drawing d, cursor c)
56 {
57     POINT pt;
58 
59     decrease_refcount(d->drawstate->crsr);
60     d->drawstate->crsr = c;
61     increase_refcount(c);
62     /* ensure new cursor is shown */
63     GetCursorPos(&pt);
64     SetCursorPos(pt.x, pt.y);
65 }
66 
newtoolbar(int height)67 control newtoolbar(int height)
68 {
69     window c = current_window;
70     if (!ismdi() || !c || (c==MDIFrame)) return NULL;
71     addto(MDIFrame);
72     c->toolbar = newwindow("TOOLBAR", rect(0, 0, 100, height),
73 			   ChildWindow | Border);
74     if (c->toolbar) {
75 	DWORD wcol = GetSysColor(COLOR_MENU);
76 	hide(c->toolbar);
77 	setbackground(c->toolbar,
78 		      rgb( (wcol >> 0) &  0x000000FFL,
79 			   (wcol >> 8) &  0x000000FFL,
80 			   (wcol >> 16) &  0x000000FFL));
81     }
82     addto(c);
83     return (control) c->toolbar;
84 }
85 
86 /* Fix background color for image on the toolbar.
87    Designed to work with image in stdimc.c:
88    (a) background is pixel (0,0);
89    (b) image depth is 8 bits;
90    (c) image is changed not copied.
91 */
newtoolbutton(image img,rect r,actionfn fn)92 button newtoolbutton(image img, rect r, actionfn fn) {
93     DWORD wcol = GetSysColor(COLOR_MENU);
94     rgb    col = rgb( (wcol >> 0) &  0x000000FFL,
95 		      (wcol >> 8) &  0x000000FFL,
96 		      (wcol >> 16) &  0x000000FFL);
97     img->cmap[img->pixels[0]] = col;
98     return newimagebutton(img, r, fn);
99 }
100 
101 
scrolltext(textbox c,int lines)102 void scrolltext(textbox c, int lines)
103 {
104     int linecount = sendmessage(c->handle, EM_GETLINECOUNT, 0, 0);
105     sendmessage(c->handle, EM_LINESCROLL, 0, linecount - lines);
106 }
107 
108 
ggetkeystate()109 int ggetkeystate()
110 {
111     int k = 0;
112     if (GetKeyState(VK_CONTROL)&0x8000)
113 	k |= CtrlKey;
114     if (GetKeyState(VK_MENU)&0x8000)
115 	k |= AltKey;
116     if (GetKeyState(VK_SHIFT)&0x8000)
117 	k |= ShiftKey;
118     return k;
119 }
120 
121 
122 /* Extra text editing functions for R, Chris Jackson */
123 #include <richedit.h>
124 
125 /* Move the editor caret position lines down.
126    If lines is negative moves caret up.
127    Stops at the top or the bottom if lines is too big or small.
128 */
129 
scrollcaret(textbox t,int lines)130 void scrollcaret(textbox t, int lines)
131 {
132     long currentline, charindex;
133     int linecount = sendmessage(t->handle, EM_GETLINECOUNT, 0, 0);
134     currentline = sendmessage(t->handle, EM_LINEFROMCHAR, -1, 0);
135     lines = (currentline + lines > linecount - 1  ?  linecount - currentline - 1 :  lines);
136     lines = (currentline + lines < 0  ?  - currentline  :  lines);
137     charindex = sendmessage(t->handle, EM_LINEINDEX, currentline + lines, 0);
138     sendmessage(t->handle, EM_SETSEL, charindex, charindex);
139 }
140 
141 /* Modification flags for the text editor */
142 
gsetmodified(textbox t,int modified)143 void gsetmodified(textbox t, int modified)
144 {
145     sendmessage(t->handle, EM_SETMODIFY, (WPARAM) modified, 0);
146 }
147 
ggetmodified(textbox t)148 int ggetmodified(textbox t)
149 {
150     return sendmessage(t->handle, EM_GETMODIFY, 0, 0);
151 }
152 
153 /* Get the length of the current line in an editing control */
154 
getlinelength(textbox t)155 int getlinelength(textbox t)
156 {
157     long charindex = sendmessage(t->handle, EM_LINEINDEX, -1, 0);
158     return sendmessage(t->handle, EM_LINELENGTH, charindex, 0);
159 }
160 
161 /* Copy the current line in the editor to a buffer */
162 
getcurrentline(textbox t,char * line,int length)163 void getcurrentline(textbox t, char *line, int length)
164 {
165     long currentline = sendmessage(t->handle, EM_LINEFROMCHAR, -1, 0);
166     *((LPWORD) line) = length*sizeof(WCHAR)+2; /* set first word of buffer to line length in TCHARs as required by EM_GETLINE */
167     sendmessage(t->handle, EM_GETLINE, currentline, line);
168     /* line[length] = 0; */
169 }
170 
171 /* Copy the current selection in the editor to a buffer */
172 
getseltext(textbox t,char * text)173 void getseltext(textbox t, char *text)
174 {
175     sendmessage(t->handle, EM_GETSELTEXT, 0, text);
176 }
177 
178 /* Change the maximum number of characters (in bytes) allowed in an editor */
179 
setlimittext(textbox t,long limit)180 void setlimittext(textbox t, long limit)
181 {
182     sendmessage(t->handle, EM_EXLIMITTEXT, 0, limit);
183 }
184 
getlimittext(textbox t)185 long getlimittext(textbox t)
186 {
187     return sendmessage(t->handle, EM_GETLIMITTEXT, 0, 0);
188 }
189 
190 /* Test whether the text limit needs to be increased to accommodate
191    some new text of length n. If so increase it by required amount
192    plus 32K.  */
193 
checklimittext(textbox t,long n)194 void checklimittext(textbox t, long n)
195 {
196     long limit = getlimittext(t);
197     long len =  GetWindowTextLength(t->handle);
198     if (len + n >= limit)
199 	setlimittext(t, len + n + 0x8000);
200 }
201 
202 /* Length of text in the clipboard */
203 
getpastelength()204 long getpastelength()
205 {
206     HGLOBAL hglb;
207     char *text;
208     long pastelen;
209     if ( OpenClipboard(NULL) &&
210 	 (hglb = GetClipboardData(CF_TEXT)) &&
211 	 (text = (char *)GlobalLock(hglb))) {
212 	pastelen = strlen(text);
213 	GlobalUnlock(hglb);
214 	CloseClipboard();
215     } else pastelen = 0;
216     return pastelen;
217 }
218 
219 /* Modification of the text selection functions in buttons.c to work
220    with the EX messages used in rich edit controls. The selection
221    messages without EX cannot handle more than 64K of text */
222 
textselectionex(control obj,long * start,long * end)223 void textselectionex(control obj, long *start, long *end)
224 {
225     CHARRANGE sel;
226     if (! obj)
227 	return;
228     if ((obj->kind != FieldObject) && (obj->kind != TextboxObject))
229 	return;
230     sendmessage(obj->handle, EM_EXGETSEL, 0, &sel);
231     *start = sel.cpMin;
232     *end = sel.cpMax;
233 }
234 
selecttextex(control obj,long start,long end)235 void selecttextex(control obj, long start, long end)
236 {
237     CHARRANGE sel;
238     long length;
239 
240     if (! obj)
241 	return;
242     if ((obj->kind != FieldObject) && (obj->kind != TextboxObject))
243 	return;
244     length = GetWindowTextLength(obj->handle);
245     sel.cpMin = (start < 0) ? length : start;
246     sel.cpMax = (end < 0) ? length : end;
247     sendmessage(obj->handle, EM_EXSETSEL, 0, &sel);
248 }
249