]>
Commit | Line | Data |
---|---|---|
14c7c974 A |
1 | /* |
2 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights | |
7 | * Reserved. This file contains Original Code and/or Modifications of | |
8 | * Original Code as defined in and that are subject to the Apple Public | |
9 | * Source License Version 1.1 (the "License"). You may not use this file | |
10 | * except in compliance with the License. Please obtain a copy of the | |
11 | * License at http://www.apple.com/publicsource and read it before using | |
12 | * this file. | |
13 | * | |
14 | * The Original Code and all software distributed under the License are | |
15 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
18 | * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the | |
19 | * License for the specific language governing rights and limitations | |
20 | * under the License. | |
21 | * | |
22 | * @APPLE_LICENSE_HEADER_END@ | |
23 | */ | |
24 | /* | |
25 | * Copyright 1993 NeXT, Inc. | |
26 | * All rights reserved. | |
27 | */ | |
28 | ||
29 | #import "libsa.h" | |
30 | #import "console.h" | |
31 | #import "fontio.h" | |
32 | #import "graphics.h" | |
33 | #import "button.h" | |
34 | #import "browser.h" | |
35 | #import "scrollbar.h" | |
36 | #import "ns_logo.h" | |
37 | #import "dot.h" | |
38 | #import "hdot.h" | |
39 | #import "keys.h" | |
40 | ||
41 | #define max(a,b) ((a) > (b) ? (a) : (b)) | |
42 | #define min(a,b) ((a) < (b) ? (a) : (b)) | |
43 | ||
44 | browser_t * | |
45 | createBrowser( | |
46 | char **items, | |
47 | int nitems, | |
48 | char *top_message, | |
49 | char *bottom_message, | |
50 | char *button_string, | |
51 | int type | |
52 | ) | |
53 | { | |
54 | browser_t *bp; | |
55 | register int i; | |
56 | ||
57 | bp = (browser_t *)zalloc(sizeof(browser_t)); | |
58 | bp->items = items; | |
59 | bp->nitems = nitems; | |
60 | bp->bot_visible = min( MAX_ITEMS_VISIBLE - 1, nitems - 1 ); | |
61 | /* bp->top_visible = 0; */ | |
62 | ||
63 | bp->top_message = top_message; | |
64 | bp->top_h = max (strheight(bp->top_message), ns_logo_bitmap_HEIGHT); | |
65 | bp->top_w = strwidth(bp->top_message) + ns_logo_bitmap_WIDTH + | |
66 | BROWSER_XMARGIN; | |
67 | bp->bottom_message = bottom_message; | |
68 | bp->bottom_h = bottom_message ? | |
69 | strheight(bottom_message) : | |
70 | -BROWSER_YMARGIN; | |
71 | bp->bottom_w = strwidth(bottom_message); | |
72 | if (nitems) { | |
73 | bp->selected = (char *)zalloc(nitems); | |
74 | if (type == BROWSER_CURRENT_IS_SELECTED) | |
75 | bp->selected[0] = 1; | |
76 | bp->item_h = strheight(items[0]); | |
77 | for(i=0; i < nitems; i++) | |
78 | bp->item_w = max(bp->item_w, strwidth(items[i])); | |
79 | bp->item_w += 2 * BROWSER_XMARGIN + dot_bitmap_WIDTH; | |
80 | bp->item_box_w = bp->item_w + 2 * BROWSER_XMARGIN; | |
81 | bp->item_box_h = bp->item_h * (bp->bot_visible - bp->top_visible + 1) | |
82 | + 2 * BROWSER_YMARGIN; | |
83 | initScrollbar(&bp->scrollbar, 0, 0, SB_WIDTH, | |
84 | bp->item_box_h - 2 * POPUP_FRAME_MARGIN, | |
85 | 0, (bp->bot_visible - bp->top_visible + 1) * 100 / bp->nitems); | |
86 | bp->item_box_w += SB_WIDTH + POPUP_FRAME_MARGIN; | |
87 | } else { | |
88 | bp->item_box_h = -BROWSER_YMARGIN; | |
89 | } | |
90 | initButton(&bp->button, 0, 0, button_string, BUTTON_DRAW_RETURN); | |
91 | bp->h = bp->top_h + bp->item_box_h + bp->bottom_h + | |
92 | bp->button.loc.h + 5 * BROWSER_YMARGIN; | |
93 | bp->w = max(bp->top_w, bp->bottom_w); | |
94 | bp->w = max(bp->w, bp->item_box_w) + 2 * BROWSER_XMARGIN; | |
95 | bp->x = (SCREEN_W - bp->w) / 2; | |
96 | bp->y = (SCREEN_H - bp->h) / 2; | |
97 | if (nitems) { | |
98 | bp->item_box_x = bp->x + (bp->w - bp->item_box_w) / 2; | |
99 | bp->scrollbar.loc.x = bp->item_box_x + POPUP_FRAME_MARGIN; | |
100 | bp->item_box_y = bp->y + 2 * BROWSER_YMARGIN + bp->top_h; | |
101 | bp->scrollbar.loc.y = bp->item_box_y + POPUP_FRAME_MARGIN; | |
102 | } | |
103 | bp->bottom_y = bp->y + 3 * BROWSER_YMARGIN + bp->top_h + bp->item_box_h; | |
104 | bp->button.loc.x = bp->x + bp->w - bp->button.loc.w - BROWSER_XMARGIN; | |
105 | bp->button.loc.y = bp->y + bp->h - bp->button.loc.h - BROWSER_YMARGIN; | |
106 | ||
107 | bp->type = type; | |
108 | ||
109 | return bp; | |
110 | } | |
111 | ||
112 | inline void | |
113 | destroyBrowser( | |
114 | browser_t *bp | |
115 | ) | |
116 | { | |
117 | /* destroyButton(bp->button); */ | |
118 | /* destroyScrollbar(bp->scrollbar); */ | |
119 | zfree((char *)bp); | |
120 | } | |
121 | ||
122 | static int item_y( | |
123 | browser_t *bp, | |
124 | int item_num | |
125 | ) | |
126 | { | |
127 | return ((bp)->item_box_y + BROWSER_YMARGIN + | |
128 | (item_num - bp->top_visible) * (bp)->item_h + (bp)->item_h / 2); | |
129 | } | |
130 | ||
131 | setItemHighlight(browser_t *bp, int item, int highlight) | |
132 | { | |
133 | register int xpos = bp->item_box_x + POPUP_FRAME_MARGIN + | |
134 | SB_WIDTH + BROWSER_XMARGIN; | |
135 | if (currentMode() != GRAPHICS_MODE || | |
136 | item < bp->top_visible || | |
137 | item > bp->bot_visible) | |
138 | return; | |
139 | blit_clear(bp->item_w, xpos, item_y(bp, item), | |
140 | CENTER_V, highlight ? COLOR_WHITE : TEXT_BG); | |
141 | if (bp->selected[item]) | |
142 | copyImage( highlight ? &hdot_bitmap : &dot_bitmap, | |
143 | xpos, | |
144 | item_y(bp, item) - dot_bitmap_HEIGHT/2); | |
145 | xpos += BROWSER_XMARGIN + dot_bitmap_WIDTH; | |
146 | blit_string(bp->items[item], xpos, item_y(bp, item), | |
147 | TEXT_FG, CENTER_V); | |
148 | } | |
149 | ||
150 | static void drawItembox(browser_t *bp) | |
151 | { | |
152 | register int i; | |
153 | bp->scrollbar.position = bp->top_visible * 100 / bp->nitems; | |
154 | drawScrollbar(&bp->scrollbar); | |
155 | for(i = bp->top_visible; i <= bp->bot_visible; i++) | |
156 | setItemHighlight(bp, i, i == bp->current); | |
157 | } | |
158 | ||
159 | static char *Separator = "----------------------------------------\n"; | |
160 | ||
161 | void drawBrowser(browser_t *bp) | |
162 | { | |
163 | short item_y; | |
164 | register int i; | |
165 | ||
166 | clearActivityIndicator(); | |
167 | if (currentMode() == TEXT_MODE) { | |
168 | printf("%s", Separator); | |
169 | if (bp->top_message) { | |
170 | printf("%s\n%s",bp->top_message, Separator); | |
171 | } | |
172 | if (bp->nitems) { | |
173 | for (i = bp->top_visible; i <= bp->bot_visible; i++) { | |
174 | printf("% 2d. %c %s\n",i+1, | |
175 | bp->selected[i] ? '*' : ' ', | |
176 | bp->items[i]); | |
177 | } | |
178 | if (bp->bot_visible != bp->nitems - 1) | |
179 | printf("......<More>\n"); | |
180 | printf(Separator); | |
181 | } | |
182 | if (bp->bottom_message) { | |
183 | printf("%s\n",bp->bottom_message); | |
184 | } | |
185 | printf(">> "); | |
186 | } else { /* GRAPHICS_MODE */ | |
187 | popupBox(bp->x, bp->y, bp->w, bp->h, TEXT_BG, POPUP_OUT); | |
188 | copyImage(&ns_logo_bitmap, bp->x + BROWSER_XMARGIN, | |
189 | bp->y + BROWSER_YMARGIN + (bp->top_h - ns_logo_bitmap_HEIGHT)/2 ); | |
190 | blit_string(bp->top_message, | |
191 | bp->x + ns_logo_bitmap_WIDTH + 2 * BROWSER_XMARGIN, | |
192 | bp->y + (bp->top_h / 2) + BROWSER_YMARGIN, | |
193 | TEXT_FG, CENTER_V); | |
194 | if (bp->bottom_message) | |
195 | blit_string(bp->bottom_message, | |
196 | bp->x + bp->w / 2, bp->bottom_y + bp->bottom_h / 2, | |
197 | TEXT_FG, CENTER_H | CENTER_V); | |
198 | drawButton(&bp->button); | |
199 | /* draw all items and highlight item 0 */ | |
200 | if (bp->nitems) { | |
201 | popupBox(bp->item_box_x, bp->item_box_y, | |
202 | bp->item_box_w, bp->item_box_h, | |
203 | TEXT_BG, POPUP_IN); | |
204 | drawItembox(bp); | |
205 | } | |
206 | } | |
207 | } | |
208 | ||
209 | clearBrowser(browser_t *bp) | |
210 | { | |
211 | if (currentMode() == GRAPHICS_MODE) | |
212 | clearBox(bp->x, bp->y, bp->w, bp->h); | |
213 | } | |
214 | ||
215 | ||
216 | selectItem(browser_t *bp, int item) | |
217 | { | |
218 | int i; | |
219 | if (bp->selected[item] == 0 && | |
220 | (bp->type == BROWSER_CURRENT_IS_SELECTED)) { | |
221 | for (i=0; i < bp->nitems; i++) | |
222 | if (bp->selected[i]) { | |
223 | bp->selected[i] = 0; | |
224 | setItemHighlight(bp, i, i == bp->current); | |
225 | } | |
226 | } | |
227 | bp->selected[item] = !bp->selected[item]; | |
228 | setItemHighlight(bp, item, item == bp->current); | |
229 | } | |
230 | ||
231 | runBrowser(browser_t *bp) | |
232 | { | |
233 | int c, i; | |
234 | char *s; | |
235 | ||
236 | if (bp->nitems == 0) { | |
237 | while ((c = getc() != '\r')); | |
238 | putc('\n'); | |
239 | return; | |
240 | } | |
241 | ||
242 | if (currentMode() == TEXT_MODE) { | |
243 | s = zalloc(128); | |
244 | for(;;) { | |
245 | gets(s, 128); | |
246 | if ((*s == 'f') || (*s == 'F')) { | |
247 | if (currentMode() == TEXT_MODE) | |
248 | if (bp->bot_visible != bp->nitems - 1) { | |
249 | bp->top_visible += MAX_ITEMS_VISIBLE; | |
250 | bp->bot_visible += MAX_ITEMS_VISIBLE; | |
251 | bp->bot_visible = min(bp->nitems - 1, bp->bot_visible); | |
252 | drawBrowser(bp); | |
253 | continue; | |
254 | } | |
255 | } else if ((*s == 'b') || (*s == 'B')) { | |
256 | if (currentMode() == TEXT_MODE) | |
257 | if (bp->top_visible >= MAX_ITEMS_VISIBLE) { | |
258 | bp->top_visible -= MAX_ITEMS_VISIBLE; | |
259 | bp->bot_visible = bp->top_visible + | |
260 | MAX_ITEMS_VISIBLE - 1; | |
261 | drawBrowser(bp); | |
262 | continue; | |
263 | } | |
264 | } | |
265 | if (*s == '\0') | |
266 | return; | |
267 | i = atoi(s); | |
268 | if (i < 1 || i > bp->nitems) { | |
269 | printf("Please enter a number between 1 and %d.\n" | |
270 | "Press <Return>:", | |
271 | bp->nitems); | |
272 | while ((c = getc()) != '\r'); | |
273 | } else { | |
274 | selectItem(bp, i-1); | |
275 | } | |
276 | drawBrowser(bp); | |
277 | } | |
278 | zfree(s); | |
279 | return; | |
280 | } | |
281 | ||
282 | for(;;) { | |
283 | switch((c = getc())) { | |
284 | case 'j': | |
285 | case K_DOWN: | |
286 | if (bp->current == bp->bot_visible && | |
287 | bp->bot_visible != bp->nitems - 1) { | |
288 | bp->top_visible++; | |
289 | bp->bot_visible++; | |
290 | bp->current++; | |
291 | if (bp->type == BROWSER_CURRENT_IS_SELECTED) | |
292 | selectItem(bp, bp->current); | |
293 | drawItembox(bp); | |
294 | } else if (bp->current < bp->nitems - 1) { | |
295 | setItemHighlight(bp, bp->current, 0); | |
296 | bp->current++; | |
297 | if (bp->type == BROWSER_CURRENT_IS_SELECTED) | |
298 | selectItem(bp, bp->current); | |
299 | else | |
300 | setItemHighlight(bp, bp->current, 1); | |
301 | } | |
302 | break; | |
303 | case 'k': | |
304 | case K_UP: | |
305 | if (bp->current == bp->top_visible && | |
306 | bp->top_visible != 0) { | |
307 | bp->top_visible--; | |
308 | bp->bot_visible--; | |
309 | bp->current--; | |
310 | if (bp->type == BROWSER_CURRENT_IS_SELECTED) | |
311 | selectItem(bp, bp->current); | |
312 | drawItembox(bp); | |
313 | } else if (bp->current > 0) { | |
314 | setItemHighlight(bp, bp->current, 0); | |
315 | bp->current--; | |
316 | if (bp->type == BROWSER_CURRENT_IS_SELECTED) | |
317 | selectItem(bp, bp->current); | |
318 | else | |
319 | setItemHighlight(bp, bp->current, 1); | |
320 | } | |
321 | break; | |
322 | case ' ': | |
323 | if (!(bp->type == BROWSER_CURRENT_IS_SELECTED)) | |
324 | selectItem(bp, bp->current); | |
325 | break; | |
326 | case '\r': | |
327 | case '\n': | |
328 | return; | |
329 | } | |
330 | } | |
331 | } | |
332 | ||
333 | static browser_t *_doBrowser( | |
334 | char **items, | |
335 | int nitems, | |
336 | char *top_message, | |
337 | char *bottom_message, | |
338 | char *button_string, | |
339 | int type | |
340 | ) | |
341 | { | |
342 | browser_t *bp; | |
343 | ||
344 | bp = createBrowser(items, nitems, | |
345 | top_message, bottom_message, button_string, type); | |
346 | drawBrowser(bp); | |
347 | runBrowser(bp); | |
348 | clearBrowser(bp); | |
349 | return bp; | |
350 | } | |
351 | ||
352 | /* | |
353 | * returns an array of characters, one per item, | |
354 | * that are set to 0 if the item was not selected, | |
355 | * 1 if the item was selected. | |
356 | */ | |
357 | char * popupBrowser( | |
358 | char **items, | |
359 | int nitems, | |
360 | char *top_message, | |
361 | char *bottom_message, | |
362 | char *button_string, | |
363 | int type | |
364 | ) | |
365 | { | |
366 | browser_t *bp; | |
367 | register char *selected; | |
368 | ||
369 | bp = _doBrowser(items, nitems, | |
370 | top_message, bottom_message, button_string, type); | |
371 | selected = bp->selected; | |
372 | destroyBrowser(bp); | |
373 | return selected; | |
374 | } | |
375 | ||
376 | void popupPanel( | |
377 | char *message | |
378 | ) | |
379 | { | |
380 | browser_t *bp; | |
381 | ||
382 | bp = _doBrowser(0, 0, | |
383 | message, 0, "Continue", 0); | |
384 | zfree(bp->selected); | |
385 | destroyBrowser(bp); | |
386 | } | |
387 | ||
388 |