Mercurial > hg > xemacs-beta
comparison src/scrollbar-msw.c @ 428:3ecd8885ac67 r21-2-22
Import from CVS: tag r21-2-22
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:28:15 +0200 |
parents | |
children | abe6d1db359e |
comparison
equal
deleted
inserted
replaced
427:0a0253eac470 | 428:3ecd8885ac67 |
---|---|
1 /* scrollbar implementation -- mswindows interface. | |
2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois. | |
3 Copyright (C) 1994 Amdahl Corporation. | |
4 Copyright (C) 1995 Sun Microsystems, Inc. | |
5 Copyright (C) 1995 Darrell Kindred <dkindred+@cmu.edu>. | |
6 | |
7 This file is part of XEmacs. | |
8 | |
9 XEmacs is free software; you can redistribute it and/or modify it | |
10 under the terms of the GNU General Public License as published by the | |
11 Free Software Foundation; either version 2, or (at your option) any | |
12 later version. | |
13 | |
14 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 for more details. | |
18 | |
19 You should have received a copy of the GNU General Public License | |
20 along with XEmacs; see the file COPYING. If not, write to | |
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
22 Boston, MA 02111-1307, USA. */ | |
23 | |
24 /* Synched up with: Not in FSF. */ | |
25 | |
26 #include <config.h> | |
27 #include <limits.h> | |
28 #include "lisp.h" | |
29 | |
30 #include "console-msw.h" | |
31 #include "events.h" | |
32 #include "frame.h" | |
33 #include "scrollbar-msw.h" | |
34 #include "scrollbar.h" | |
35 #include "specifier.h" | |
36 #include "window.h" | |
37 | |
38 /* We use a similar sort of vertical scrollbar drag hack for mswindows | |
39 * scrollbars as is used for Motif or Lucid scrollbars under X. | |
40 * We do character-based instead of line-based scrolling, which can mean that | |
41 * without the hack it is impossible to drag to the end of a buffer. */ | |
42 #define VERTICAL_SCROLLBAR_DRAG_HACK | |
43 | |
44 static int vertical_drag_in_progress = 0; | |
45 | |
46 static void | |
47 mswindows_create_scrollbar_instance (struct frame *f, int vertical, | |
48 struct scrollbar_instance *sb) | |
49 { | |
50 int orientation; | |
51 | |
52 sb->scrollbar_data = xnew_and_zero (struct mswindows_scrollbar_data); | |
53 | |
54 if (vertical) | |
55 orientation = SBS_VERT; | |
56 else | |
57 orientation = SBS_HORZ; | |
58 | |
59 SCROLLBAR_MSW_HANDLE (sb) = | |
60 CreateWindowEx(0, "SCROLLBAR", 0, orientation|WS_CHILD, | |
61 CW_USEDEFAULT, CW_USEDEFAULT, | |
62 CW_USEDEFAULT, CW_USEDEFAULT, | |
63 FRAME_MSWINDOWS_HANDLE (f), | |
64 NULL, NULL, NULL); | |
65 SCROLLBAR_MSW_INFO (sb).cbSize = sizeof(SCROLLINFO); | |
66 SCROLLBAR_MSW_INFO (sb).fMask = SIF_ALL; | |
67 GetScrollInfo(SCROLLBAR_MSW_HANDLE (sb), SB_CTL, | |
68 &SCROLLBAR_MSW_INFO (sb)); | |
69 SetWindowLong (SCROLLBAR_MSW_HANDLE(sb), GWL_USERDATA, (LONG)sb); | |
70 | |
71 #if 0 | |
72 { | |
73 HWND h = SCROLLBAR_MSW_HANDLE (sb); | |
74 int x = SetWindowLong (SCROLLBAR_MSW_HANDLE(sb), GWL_USERDATA, (LONG)sb); | |
75 int y = GetLastError(); | |
76 struct scrollbar_instance *z = (struct scrollbar_instance *)GetWindowLong (SCROLLBAR_MSW_HANDLE(sb), | |
77 GWL_USERDATA); | |
78 *z = *z; | |
79 } | |
80 #endif | |
81 } | |
82 | |
83 static void | |
84 mswindows_free_scrollbar_instance (struct scrollbar_instance *sb) | |
85 { | |
86 DestroyWindow (SCROLLBAR_MSW_HANDLE (sb)); | |
87 if (sb->scrollbar_data) | |
88 xfree (sb->scrollbar_data); | |
89 } | |
90 | |
91 static void | |
92 mswindows_release_scrollbar_instance (struct scrollbar_instance *sb) | |
93 { | |
94 ShowScrollBar (SCROLLBAR_MSW_HANDLE (sb), SB_CTL, 0); | |
95 SCROLLBAR_MSW_SIZE (sb) = 0; | |
96 } | |
97 | |
98 #define UPDATE_POS_FIELD(field) \ | |
99 if (new_##field >= 0 && SCROLLBAR_MSW_DATA (sb)->field != new_##field) { \ | |
100 SCROLLBAR_MSW_DATA (sb)->field = new_##field; \ | |
101 pos_changed = 1; \ | |
102 } | |
103 | |
104 static void | |
105 mswindows_update_scrollbar_instance_values (struct window *w, | |
106 struct scrollbar_instance *sb, | |
107 int new_line_increment, | |
108 int new_page_increment, | |
109 int new_minimum, int new_maximum, | |
110 int new_slider_size, | |
111 int new_slider_position, | |
112 int new_scrollbar_width, | |
113 int new_scrollbar_height, | |
114 int new_scrollbar_x, | |
115 int new_scrollbar_y) | |
116 { | |
117 int pos_changed = 0; | |
118 int vert = GetWindowLong (SCROLLBAR_MSW_HANDLE (sb), GWL_STYLE) & SBS_VERT; | |
119 | |
120 #if 0 | |
121 stderr_out ("[%d, %d], page = %d, pos = %d, inhibit = %d\n", new_minimum, new_maximum, | |
122 new_slider_size, new_slider_position,inhibit_slider_size_change); | |
123 #endif | |
124 | |
125 /* These might be optimized, but since at least one will change at each | |
126 call, it's probably not worth it. */ | |
127 SCROLLBAR_MSW_INFO (sb).nMin = new_minimum; | |
128 SCROLLBAR_MSW_INFO (sb).nMax = new_maximum; | |
129 SCROLLBAR_MSW_INFO (sb).nPage = new_slider_size + 1; /* +1 for DISABLENOSCROLL */ | |
130 SCROLLBAR_MSW_INFO (sb).nPos = new_slider_position; | |
131 #ifndef VERTICAL_SCROLLBAR_DRAG_HACK | |
132 SCROLLBAR_MSW_INFO (sb).fMask = ((vert && vertical_drag_in_progress) | |
133 ? SIF_RANGE | SIF_POS | |
134 : SIF_ALL | SIF_DISABLENOSCROLL); | |
135 #else | |
136 SCROLLBAR_MSW_INFO (sb).fMask = SIF_ALL | SIF_DISABLENOSCROLL; | |
137 | |
138 /* Ignore XEmacs' requests to update the thumb position and size; they don't | |
139 * bear any relation to reality because we're reporting made-up positions */ | |
140 if (!(vert && vertical_drag_in_progress)) | |
141 #endif | |
142 SetScrollInfo (SCROLLBAR_MSW_HANDLE (sb), SB_CTL, &SCROLLBAR_MSW_INFO (sb), | |
143 TRUE); | |
144 | |
145 UPDATE_POS_FIELD (scrollbar_x); | |
146 UPDATE_POS_FIELD (scrollbar_y); | |
147 UPDATE_POS_FIELD (scrollbar_width); | |
148 UPDATE_POS_FIELD (scrollbar_height); | |
149 | |
150 if (pos_changed) | |
151 { | |
152 MoveWindow(SCROLLBAR_MSW_HANDLE (sb), | |
153 new_scrollbar_x, new_scrollbar_y, | |
154 new_scrollbar_width, new_scrollbar_height, | |
155 TRUE); | |
156 } | |
157 } | |
158 | |
159 static void | |
160 mswindows_update_scrollbar_instance_status (struct window *w, | |
161 int active, int size, | |
162 struct scrollbar_instance *sb) | |
163 { | |
164 if (SCROLLBAR_MSW_SIZE (sb) != size) | |
165 { | |
166 SCROLLBAR_MSW_SIZE (sb) = size; | |
167 ShowScrollBar (SCROLLBAR_MSW_HANDLE (sb), SB_CTL, | |
168 SCROLLBAR_MSW_SIZE (sb)); | |
169 SCROLLBAR_MSW_INFO(sb).fMask |= SIF_DISABLENOSCROLL; | |
170 SetScrollInfo(SCROLLBAR_MSW_HANDLE (sb), SB_CTL, &SCROLLBAR_MSW_INFO (sb), TRUE); | |
171 } | |
172 } | |
173 | |
174 void | |
175 mswindows_handle_scrollbar_event (HWND hwnd, int code, int pos) | |
176 { | |
177 struct frame *f; | |
178 Lisp_Object win, frame; | |
179 struct scrollbar_instance *sb; | |
180 SCROLLINFO scrollinfo; | |
181 int vert = GetWindowLong (hwnd, GWL_STYLE) & SBS_VERT; | |
182 int value; | |
183 | |
184 sb = (struct scrollbar_instance *)GetWindowLong (hwnd, GWL_USERDATA); | |
185 win = real_window (sb->mirror, 1); | |
186 frame = XWINDOW (win)->frame; | |
187 f = XFRAME (frame); | |
188 | |
189 /* SB_LINEDOWN == SB_CHARLEFT etc. This is the way they will | |
190 always be - any Windows is binary compatible backward with | |
191 old programs */ | |
192 | |
193 switch (code) | |
194 { | |
195 case SB_LINEDOWN: | |
196 mswindows_enqueue_misc_user_event | |
197 (frame, vert ? Qscrollbar_line_down : Qscrollbar_char_right, win); | |
198 break; | |
199 | |
200 case SB_LINEUP: | |
201 mswindows_enqueue_misc_user_event | |
202 (frame, vert ? Qscrollbar_line_up : Qscrollbar_char_left, win); | |
203 break; | |
204 | |
205 case SB_PAGEDOWN: | |
206 mswindows_enqueue_misc_user_event | |
207 (win, vert ? Qscrollbar_page_down : Qscrollbar_page_right, | |
208 vert ? Fcons (win, Qnil) : win); | |
209 break; | |
210 | |
211 case SB_PAGEUP: | |
212 mswindows_enqueue_misc_user_event | |
213 (frame, | |
214 vert ? Qscrollbar_page_up : Qscrollbar_page_left, | |
215 vert ? Fcons (win, Qnil) : win); | |
216 break; | |
217 | |
218 case SB_BOTTOM: | |
219 mswindows_enqueue_misc_user_event | |
220 (frame, vert ? Qscrollbar_to_bottom : Qscrollbar_to_right, win); | |
221 break; | |
222 | |
223 case SB_TOP: | |
224 mswindows_enqueue_misc_user_event | |
225 (frame, vert ? Qscrollbar_to_top : Qscrollbar_to_left, win); | |
226 break; | |
227 | |
228 case SB_THUMBTRACK: | |
229 case SB_THUMBPOSITION: | |
230 scrollinfo.cbSize = sizeof(SCROLLINFO); | |
231 scrollinfo.fMask = SIF_ALL; | |
232 GetScrollInfo (hwnd, SB_CTL, &scrollinfo); | |
233 vertical_drag_in_progress = vert; | |
234 #ifdef VERTICAL_SCROLLBAR_DRAG_HACK | |
235 if (vert && (scrollinfo.nTrackPos > scrollinfo.nPos)) | |
236 /* new buffer position = | |
237 * buffer position at start of drag + | |
238 * ((text remaining in buffer at start of drag) * | |
239 * (amount that the thumb has been moved) / | |
240 * (space that remained past end of the thumb at start of drag)) */ | |
241 value = (int) | |
242 (scrollinfo.nPos | |
243 + (((double) | |
244 (scrollinfo.nMax - scrollinfo.nPos) | |
245 * (scrollinfo.nTrackPos - scrollinfo.nPos)) | |
246 / (scrollinfo.nMax - scrollinfo.nPage - scrollinfo.nPos))) | |
247 - 2; /* ensure that the last line doesn't disappear off screen */ | |
248 else | |
249 #endif | |
250 value = scrollinfo.nTrackPos; | |
251 mswindows_enqueue_misc_user_event | |
252 (frame, | |
253 vert ? Qscrollbar_vertical_drag : Qscrollbar_horizontal_drag, | |
254 Fcons (win, make_int (value))); | |
255 break; | |
256 | |
257 case SB_ENDSCROLL: | |
258 #ifdef VERTICAL_SCROLLBAR_DRAG_HACK | |
259 if (vertical_drag_in_progress) | |
260 /* User has just dropped the thumb - finally update it */ | |
261 SetScrollInfo (SCROLLBAR_MSW_HANDLE (sb), SB_CTL, | |
262 &SCROLLBAR_MSW_INFO (sb), TRUE); | |
263 #endif | |
264 vertical_drag_in_progress = 0; | |
265 break; | |
266 } | |
267 } | |
268 | |
269 static int | |
270 can_scroll(struct scrollbar_instance* scrollbar) | |
271 { | |
272 return scrollbar != NULL | |
273 && IsWindowVisible (SCROLLBAR_MSW_HANDLE (scrollbar)) | |
274 && IsWindowEnabled (SCROLLBAR_MSW_HANDLE (scrollbar)); | |
275 } | |
276 | |
277 int | |
278 mswindows_handle_mousewheel_event (Lisp_Object frame, int keys, int delta) | |
279 { | |
280 int hasVertBar, hasHorzBar; /* Indicates prescence of scroll bars */ | |
281 unsigned wheelScrollLines = 0; /* Number of lines per wheel notch */ | |
282 | |
283 /* Find the currently selected window */ | |
284 Lisp_Object win = FRAME_SELECTED_WINDOW (XFRAME (frame)); | |
285 struct window* w = XWINDOW (win); | |
286 struct window_mirror* mirror = find_window_mirror (w); | |
287 | |
288 /* Check that there is something to scroll */ | |
289 hasVertBar = can_scroll (mirror->scrollbar_vertical_instance); | |
290 hasHorzBar = can_scroll (mirror->scrollbar_horizontal_instance); | |
291 if (!hasVertBar && !hasHorzBar) | |
292 return FALSE; | |
293 | |
294 /* No support for panning and zooming, so ignore */ | |
295 if (keys & (MK_SHIFT | MK_CONTROL)) | |
296 return FALSE; | |
297 | |
298 /* Get the number of lines per wheel delta */ | |
299 SystemParametersInfo (SPI_GETWHEELSCROLLLINES, 0, &wheelScrollLines, 0); | |
300 | |
301 /* Calculate the amount to scroll */ | |
302 if (wheelScrollLines == WHEEL_PAGESCROLL) | |
303 { | |
304 /* Scroll by a page */ | |
305 Lisp_Object function; | |
306 if (hasVertBar) | |
307 function = delta > 0 ? Qscrollbar_page_up : Qscrollbar_page_down; | |
308 else | |
309 function = delta > 0 ? Qscrollbar_page_left : Qscrollbar_page_right; | |
310 mswindows_enqueue_misc_user_event (frame, function, Fcons (win, Qnil)); | |
311 } | |
312 else /* Scroll by a number of lines */ | |
313 { | |
314 /* Calc the number of lines to scroll */ | |
315 int toScroll = MulDiv (delta, wheelScrollLines, WHEEL_DELTA); | |
316 | |
317 /* Do the scroll */ | |
318 Lisp_Object function; | |
319 if (hasVertBar) | |
320 function = delta > 0 ? Qscrollbar_line_up : Qscrollbar_line_down; | |
321 else | |
322 function = delta > 0 ? Qscrollbar_char_left : Qscrollbar_char_right; | |
323 if (toScroll < 0) | |
324 toScroll = -toScroll; | |
325 while (toScroll--) | |
326 mswindows_enqueue_misc_user_event (frame, function, win); | |
327 } | |
328 | |
329 return TRUE; | |
330 } | |
331 | |
332 #ifdef MEMORY_USAGE_STATS | |
333 | |
334 static int | |
335 mswindows_compute_scrollbar_instance_usage (struct device *d, | |
336 struct scrollbar_instance *inst, | |
337 struct overhead_stats *ovstats) | |
338 { | |
339 int total = 0; | |
340 | |
341 while (inst) | |
342 { | |
343 struct mswindows_scrollbar_data *data = | |
344 (struct mswindows_scrollbar_data *) inst->scrollbar_data; | |
345 | |
346 total += malloced_storage_size (data, sizeof (*data), ovstats); | |
347 inst = inst->next; | |
348 } | |
349 | |
350 return total; | |
351 } | |
352 | |
353 #endif /* MEMORY_USAGE_STATS */ | |
354 | |
355 /************************************************************************/ | |
356 /* Device-specific ghost specifiers initialization */ | |
357 /************************************************************************/ | |
358 | |
359 DEFUN ("mswindows-init-scrollbar-metrics", Fmswindows_init_scrollbar_metrics, 1, 1, 0, /* | |
360 */ | |
361 (locale)) | |
362 { | |
363 if (DEVICEP (locale)) | |
364 { | |
365 add_spec_to_ghost_specifier (Vscrollbar_width, | |
366 make_int (GetSystemMetrics (SM_CXVSCROLL)), | |
367 locale, Qmswindows, Qnil); | |
368 add_spec_to_ghost_specifier (Vscrollbar_height, | |
369 make_int (GetSystemMetrics (SM_CYHSCROLL)), | |
370 locale, Qmswindows, Qnil); | |
371 } | |
372 return Qnil; | |
373 } | |
374 | |
375 | |
376 /************************************************************************/ | |
377 /* initialization */ | |
378 /************************************************************************/ | |
379 | |
380 void | |
381 console_type_create_scrollbar_mswindows (void) | |
382 { | |
383 CONSOLE_HAS_METHOD (mswindows, create_scrollbar_instance); | |
384 CONSOLE_HAS_METHOD (mswindows, free_scrollbar_instance); | |
385 CONSOLE_HAS_METHOD (mswindows, release_scrollbar_instance); | |
386 CONSOLE_HAS_METHOD (mswindows, update_scrollbar_instance_values); | |
387 CONSOLE_HAS_METHOD (mswindows, update_scrollbar_instance_status); | |
388 /* CONSOLE_HAS_METHOD (mswindows, scrollbar_width_changed_in_frame); */ | |
389 #ifdef MEMORY_USAGE_STATS | |
390 CONSOLE_HAS_METHOD (mswindows, compute_scrollbar_instance_usage); | |
391 #endif | |
392 } | |
393 | |
394 void | |
395 syms_of_scrollbar_mswindows(void) | |
396 { | |
397 DEFSUBR (Fmswindows_init_scrollbar_metrics); | |
398 } | |
399 | |
400 void | |
401 vars_of_scrollbar_mswindows(void) | |
402 { | |
403 Fprovide (intern ("mswindows-scrollbars")); | |
404 } | |
405 |