1 /*---------------------------------------------------------------------------*
2  *       N I N T E N D O  C O N F I D E N T I A L  P R O P R I E T A R Y
3  *---------------------------------------------------------------------------*
4  *
5  * Project: Dolphin OS - TextWindow primitives
6  * File:    txwin.c
7  *
8  * Copyright 1999, 2000 Nintendo. All rights reserved.
9  *
10  * These coded instructions, statements, and computer programs contain
11  * proprietary information of Nintendo of America Inc. and/or Nintendo
12  * Company Ltd., and are protected by Federal copyright law.  They may
13  * not be disclosed to third parties or copied or duplicated in any form,
14  * in whole or in part, without the prior written consent of Nintendo.
15  *
16  * $Log: DEMOWin.c,v $
17  * Revision 1.3  2006/05/21 15:02:09  ekwon
18  * Revised to accommodate MEM library usage if DEMO_USE_MEMLIB is #define'd before DEMOWIN.h is included.
19  *
20  * Also supports using MEM2 via  #define of DEMOWIN_USE_MEM2. However, this has not been tested yet.
21  *
22  * Note that these changes are backwards compatible with older demos.
23  *
24  * Revision 1.2  2006/02/20 04:37:44  mitu
25  * changed include path from dolphin/ to revolution/.
26  *
27  * Revision 1.1.1.1  2005/05/12 02:15:48  yasuh-to
28  * Ported from dolphin system tree
29  *
30 
31     20    2002/08/26 10:03 Hashida
32     Deleted an unused variable.
33 
34     19    2002/02/05 4:01p Eugene
35     Added pad data to window structure so that it may be exposed to the
36     calling application.
37 
38     18    2001/07/27 11:49a Eugene
39     Failed to set window handles to NULL after freeing in
40     DEMOWinDestroy*Window() functions. Ooops, heee.
41 
42     17    2001/05/21 12:14p Eugene
43     Modified default window color to accommodate gamma 1.0
44 
45     16    2001/5/21 12:04p Eugene
46     Moved DEMOWIN.H to include/demo/demowin.h
47 
48     15    2001/05/10 12:00a Eugene
49     Debounced MNU_SELECT and MNU_RIGHT inputs
50 
51     14    2001/05/09 9:13p Eugene
52     Fixed consecutive SEPARATOR menu item bug.
53 
54     13    2001/05/09 2:20p Eugene
55 
56     12    2001/05/08 10:49p Eugene
57     1. Added Menu system.
58     2. Added List system.
59     3. No more special window types (log/state). Unified buffer system.
60     4. Windows are scrollable.
61     5. Menus support "child" menus recursively.
62     6. DEMO-lib friendly graphics for windows.
63     7. Window priority system. (using Z-buffer).
64     8. Window creation/destruction performed w/ separate API calls, to
65     facilitate handle reuse (and minimize mem allocation).
66     9. errrrmmm.....other stuff. repeat-mode pad inputs...
67 
68     11    2001/05/08 4:05a Eugene
69 
70     10    2001/05/08 2:18a Eugene
71 
72     9     2001/05/08 2:05a Eugene
73 
74     8     2001/05/07 11:54p Eugene
75 
76     7     2001/05/07 11:27p Eugene
77 
78     6     2001/05/07 11:12p Eugene
79 
80     5     2001/05/07 10:02p Eugene
81 
82     4     2001/05/07 1:28p Eugene
83 
84     3     2001/05/06 11:28p Eugene
85 
86     2     2001/05/06 11:07p Eugene
87 
88     1     2001/05/06 8:29p Eugene
89     Simple text-windowing system. Not documented, not officially supported.
90     Include <dolphin/DEMOWin.h> to use the API. Does not impact old DEMO
91     library.
92 
93     1     2000/12/04 7:28p Eugene
94  *
95  *
96  * $NoKeywords: $
97  *
98  *---------------------------------------------------------------------------*/
99 
100 
101 /*---------------------------------------------------------------------------*
102  * Includes
103  *---------------------------------------------------------------------------*/
104 #include <demo.h>
105 #include <stdlib.h>
106 #include <string.h>
107 #include <stddef.h>
108 #include <stdarg.h>
109 
110 #include <revolution.h>
111 
112 #include <demo/DEMOWin.h>
113 
114 
115 
116 /*---------------------------------------------------------------------------*
117  * Local types
118  *---------------------------------------------------------------------------*/
119 
120 
121 
122 /*---------------------------------------------------------------------------*
123  * Private module variables
124  *---------------------------------------------------------------------------*/
125 
126 DEMOWinInfo     *__first_node;
127 DEMOWinInfo     *__last_node;
128 DEMOWinInfo     *__curr_node;
129 
130 GXRenderModeObj *__rmp;
131 
132 #define __DEF_BKGND_R   0x1a
133 #define __DEF_BKGND_G   0x1f
134 #define __DEF_BKGND_B   0x21
135 #define __DEF_BKGND_A   0xff
136 
137 #define __DEF_CAP_R     0x55
138 #define __DEF_CAP_G     0x1f
139 #define __DEF_CAP_B     0x1f
140 #define __DEF_CAP_A     0xff
141 
142 #define __DEF_BORDER_R  0x45
143 #define __DEF_BORDER_G  0x25
144 #define __DEF_BORDER_B  0x25
145 #define __DEF_BORDER_A  0xff
146 
147 s32 fontShift = 0;
148 
149 static u32 __DEMOWIN_PAD_repeat_threshold = DEMOWIN_PAD_REPEAT_THRESH_DEF;
150 static u32 __DEMOWIN_PAD_repeat_rate      = DEMOWIN_PAD_REPEAT_RATE_DEF;
151 
152 
153 //
154 // hackery to use MEM library, and to specify MEM1 or MEM2
155 // based on whether or not DEMO_USE_MEMLIB and DEMOWIN_USE_MEM2 are #define'd
156 //
157 
158 static BOOL __DEMOWin_use_memlib = FALSE;
159 static BOOL __DEMOWin_use_mem2   = FALSE;
160 
161 static MEMAllocator *__DEMOWin_memallocator_ptr;
162 
163 
164 /*---------------------------------------------------------------------------*
165  * Private function prototypes
166  *---------------------------------------------------------------------------*/
167 static void  __DEMOWin_add_node              (DEMOWinInfo *handle);
168 static void  __DEMOWin_delete_node           (DEMOWinInfo *handle);
169 static void  __DEMOWin_puts_n                ( s16 x, s16 y, s16 z, u16 n, char* string );
170 
171 static u16   __DEMOWinMenu_get_user_input    (DEMOWinPadInfo *p);
172 static void  __DEMOWinMenu_refesh_menu       (DEMOWinInfo *w);
173 static void  __DEMOWinList_refresh_list      (DEMOWinInfo *w);
174 
175 static void *__DEMOWin_alloc                 (u32 size);
176 static void  __DEMOWin_free                  (void *ptr);
177 
178 /*---------------------------------------------------------------------------*
179  * Name        :
180  * Description :
181  * Arguments   : None.
182  * Returns     : None.
183  *---------------------------------------------------------------------------*/
__DEMOWin_alloc(u32 size)184 static void *__DEMOWin_alloc(u32 size)
185 {
186 
187     void *ptr;
188 
189         if (__DEMOWin_use_memlib)
190         {
191             ptr = MEMAllocFromAllocator(__DEMOWin_memallocator_ptr, size);
192         }
193         else
194         {
195             ptr = OSAlloc(size);
196         }
197 
198         return(ptr);
199 
200 } // End __DEMOWin_alloc()
201 
202 
203 /*---------------------------------------------------------------------------*
204  * Name        :
205  * Description :
206  * Arguments   : None.
207  * Returns     : None.
208  *---------------------------------------------------------------------------*/
__DEMOWin_free(void * ptr)209 static void  __DEMOWin_free(void *ptr)
210 {
211 
212     if (__DEMOWin_use_memlib)
213     {
214         MEMFreeToAllocator(__DEMOWin_memallocator_ptr, ptr);
215     }
216     else
217     {
218         OSFree(ptr);
219     }
220 
221 } // End __DEMOWin_free()
222 
223 /*---------------------------------------------------------------------------*
224  * Name        : DEMOWinInit()
225  *
226  * Description :
227  *
228  * Arguments   : None.
229  *
230  * Returns     : None.
231  *
232  *---------------------------------------------------------------------------*/
DEMOWinInit_Real(BOOL mem_lib_flag,BOOL mem2_flag)233 void DEMOWinInit_Real(BOOL mem_lib_flag, BOOL mem2_flag)
234 {
235 
236     __DEMOWin_use_memlib = mem_lib_flag;
237     __DEMOWin_use_mem2   = mem2_flag;
238 
239     if (__DEMOWin_use_memlib)
240     {
241         if (__DEMOWin_use_mem2)
242         {
243             __DEMOWin_memallocator_ptr = &DemoAllocator2;
244         }
245         else
246         {
247             __DEMOWin_memallocator_ptr = &DemoAllocator1;
248         }
249     }
250 
251     // Initialize window list
252     __first_node = NULL;
253     __last_node  = NULL;
254     __curr_node  = NULL;
255 
256     __rmp = DEMOGetRenderModeObj();
257 
258     GXSetCopyClear( (GXColor){ 0x00, 0x00, 0x00, 0x00 }, GX_MAX_Z24 );
259 
260 } // End winInit()
261 
262 /*---------------------------------------------------------------------------*
263  * Name        : DEMOWinCreateWindow()
264  *
265  * Description :
266  *
267  * Arguments   : None.
268  *
269  * Returns     : None.
270  *
271  *---------------------------------------------------------------------------*/
DEMOWinCreateWindow(s32 x1,s32 y1,s32 x2,s32 y2,char * caption,u16 scroll,void * func)272 DEMOWinInfo *DEMOWinCreateWindow(s32 x1, s32 y1, s32 x2, s32 y2, char *caption, u16 scroll, void *func)
273 {
274 
275     DEMOWinInfo *handle;
276 
277         ASSERTMSG((x1 < x2), "DEMOWIN: Illegal X coords for window\n");
278         ASSERTMSG((y1 < y2), "DEMOWIN: Illegal y coords for window\n");
279 
280         // Allocate window structure
281         handle = (DEMOWinInfo *)__DEMOWin_alloc(sizeof(DEMOWinInfo));
282         ASSERTMSG(handle, "DEMOWIN: FAILED TO ALLOCATE WINDOW!\n");
283 
284         handle->x1 = x1;
285         handle->y1 = y1;
286         handle->x2 = x2;
287         handle->y2 = y2;
288 
289         handle->pixel_width  = (u16)(x2 - x1 + 1);
290         handle->pixel_height = (u16)(y2 - y1 + 1);
291 
292         handle->caption = caption;
293 
294         handle->char_width  = (u16)(((handle->pixel_width)/FONT_CHAR_WIDTH)-1);     // Save a column for padding
295         handle->char_height = (u16)(((handle->pixel_height)/FONT_CHAR_HEIGHT)-2);   // Save first line for caption, extra line for padding
296 
297         handle->x_cal       = (u16)((handle->pixel_width  - (handle->char_width * FONT_CHAR_WIDTH) + 1) / 2);
298         handle->y_cal       = (u16)(((handle->pixel_height - FONT_CHAR_HEIGHT) - (handle->char_height * FONT_CHAR_HEIGHT) + 1) / 2);
299 
300 #ifdef DEMOWIN_DEBUG
301 
302         OSReport("\n");
303         OSReport("======================================\n");
304         OSReport("WINDOW: '%s'\n", caption);
305         OSReport("======================================\n");
306         OSReport("x1: %4d\n", handle->x1);
307         OSReport("y1: %4d\n", handle->y1);
308         OSReport("x2: %4d\n", handle->x2);
309         OSReport("y2: %4d\n", handle->y2);
310         OSReport("pixel_width : %4d\n", handle->pixel_width);
311         OSReport("pixel_height: %4d\n", handle->pixel_height);
312         OSReport("char_width  : %4d\n", handle->char_width);
313         OSReport("char_height : %4d\n", handle->char_height);
314         OSReport("x_cal       : %4d\n", handle->x_cal);
315         OSReport("y_cal       : %4d\n", handle->y_cal);
316 
317 #endif
318 
319         handle->num_scroll_lines = scroll;
320 
321         handle->total_lines = (u16)(handle->char_height + handle->num_scroll_lines);
322 
323         handle->curr_output_line = 0;
324         handle->curr_output_col  = 0;
325         handle->curr_view_line   = 0;
326 
327         // User refresh function
328         handle->refresh = func;
329 
330         // Clear flags
331         handle->flags = 0;
332 
333         // Set priority
334         handle->priority = DEMOWIN_PRIORITY_FORE;
335 
336 
337         handle->buffer = (u8 *)__DEMOWin_alloc(sizeof(u8) * handle->total_lines * handle->char_width);
338         ASSERTMSG(handle->buffer, "DEMOWinCreateWindow(): Unable to allocation buffer!\n");
339 
340         memset((void *)(handle->buffer), 0x20, sizeof(u8) * handle->total_lines * handle->char_width);
341 
342 
343         DEMOWinSetWindowColor(handle, DEMOWIN_COLOR_RESET, 0, 0, 0, 0);
344 
345         // Turn off cursor;
346         handle->cursor_line = -1;
347 
348         // Initialize parent to NULL
349         handle->parent = NULL;
350 
351 
352         // Do this last!
353         __DEMOWin_add_node(handle);
354 
355         return(handle);
356 
357 
358 } // End DEMOWinCreateWindow()
359 
360 
361 
362 /*---------------------------------------------------------------------------*
363  * Name        : DEMOWinDestroyWindow()
364  *
365  * Description :
366  *
367  * Arguments   : None.
368  *
369  * Returns     : None.
370  *
371  *---------------------------------------------------------------------------*/
DEMOWinDestroyWindow(DEMOWinInfo * handle)372 void DEMOWinDestroyWindow(DEMOWinInfo *handle)
373 {
374     BOOL old;
375 
376         ASSERTMSG(handle, "DEMOWinDestroyWindow(): NULL handle!\n");
377 
378 
379         old = OSDisableInterrupts();
380 
381         __DEMOWin_delete_node(handle);
382 
383 /*
384         for (i=0; i < handle->total_lines; i++)
385         {
386             __DEMOWin_free(handle->buffer[i]);
387         }
388 */
389         __DEMOWin_free(handle->buffer);
390 
391         __DEMOWin_free(handle);
392 
393         OSRestoreInterrupts(old);
394 
395 } // End DEMOWinDestroyWindow()
396 
397 /*---------------------------------------------------------------------------*
398  * Name        : DEMOWinOpenWindow()
399  *
400  * Description :
401  *
402  * Arguments   : None.
403  *
404  * Returns     : None.
405  *
406  *---------------------------------------------------------------------------*/
DEMOWinOpenWindow(DEMOWinInfo * handle)407 void DEMOWinOpenWindow(DEMOWinInfo *handle)
408 {
409 
410     ASSERTMSG(handle, "DEMOWinOpenWindow(): NULL handle!\n");
411     handle->flags |= DEMOWIN_FLAG_VISIBLE;
412 }
413 
414 /*---------------------------------------------------------------------------*
415  * Name        : DEMOWinCloseWindow()
416  *
417  * Description :
418  *
419  * Arguments   : None.
420  *
421  * Returns     : None.
422  *
423  *---------------------------------------------------------------------------*/
DEMOWinCloseWindow(DEMOWinInfo * handle)424 void DEMOWinCloseWindow(DEMOWinInfo *handle)
425 {
426     ASSERTMSG(handle, "DEMOWinCloseWindow(): NULL handle!\n");
427     handle->flags &= ~DEMOWIN_FLAG_VISIBLE;
428 }
429 
430 
431 /*---------------------------------------------------------------------------*
432  * Name        : DEMOWinSetWindowColor()
433  *
434  * Description :
435  *
436  * Arguments   : None.
437  *
438  * Returns     : None.
439  *
440  *---------------------------------------------------------------------------*/
DEMOWinSetWindowColor(DEMOWinInfo * handle,u32 item,u8 r,u8 g,u8 b,u8 a)441 void DEMOWinSetWindowColor(DEMOWinInfo *handle, u32 item, u8 r, u8 g, u8 b, u8 a)
442 {
443 
444     ASSERTMSG(handle, "DEMOWinSetWinColor(): NULL window handle\n");
445 
446     switch (item)
447     {
448         case DEMOWIN_COLOR_CAPTION:
449             handle->cap.r = r;
450             handle->cap.g = g;
451             handle->cap.b = b;
452             handle->cap.a = a;
453             break;
454 
455         case DEMOWIN_COLOR_BORDER:
456             handle->border.r = r;
457             handle->border.g = g;
458             handle->border.b = b;
459             handle->border.a = a;
460             break;
461 
462         case DEMOWIN_COLOR_BKGND:
463             handle->bkgnd.r = r;
464             handle->bkgnd.g = g;
465             handle->bkgnd.b = b;
466             handle->bkgnd.a = a;
467             break;
468 
469         case DEMOWIN_COLOR_RESET:
470             handle->bkgnd.r  = __DEF_BKGND_R;
471             handle->bkgnd.g  = __DEF_BKGND_G;
472             handle->bkgnd.b  = __DEF_BKGND_B;
473             handle->bkgnd.a  = __DEF_BKGND_A;
474 
475             handle->cap.r    = __DEF_CAP_R;
476             handle->cap.g    = __DEF_CAP_G;
477             handle->cap.b    = __DEF_CAP_B;
478             handle->cap.a    = __DEF_CAP_A;
479 
480             handle->border.r = __DEF_BORDER_R;
481             handle->border.g = __DEF_BORDER_G;
482             handle->border.b = __DEF_BORDER_B;
483             handle->border.a = __DEF_BORDER_A;
484             break;
485 
486         default:
487             ASSERTMSG(0, "DEMOWinSetWinColor(): Unknown item\n");
488             break;
489     } // End switch
490 
491 } // DEMOWinSetWinColor()
492 
493 
494 /*---------------------------------------------------------------------------*
495  * Name        : DEMOWinLogPrintf()
496  *
497  * Description :
498  *
499  * Arguments   : None.
500  *
501  * Returns     : None.
502  *
503  *---------------------------------------------------------------------------*/
DEMOWinLogPrintf(DEMOWinInfo * handle,char * fmt,...)504 void DEMOWinLogPrintf(DEMOWinInfo *handle, char *fmt, ...)
505 {
506     va_list vlist;
507     char    buffer[DEMOWIN_MAX_STRING_SIZE];
508     u16     len;
509     u16     i;
510     BOOL    old;
511 
512     u16     index = 0;
513 
514         // Get output string
515         va_start(vlist, fmt);
516         vsprintf(buffer, fmt, vlist);
517         va_end(vlist);
518 
519 
520         old = OSDisableInterrupts();
521 
522 
523         len = (u16)strlen(buffer);
524 
525         for (i=0; i<len; i++)
526         {
527 
528             if (buffer[i] == '\n')
529             {
530                 // Advance current output line and view line
531                 handle->curr_output_line = (u16)((handle->curr_output_line + 1) % handle->total_lines);
532                 handle->curr_view_line   = (u16)((handle->curr_view_line + 1) % handle->total_lines);
533                 handle->curr_output_col  = 0;
534 
535                 // Clobber new output line
536                 index = (u16)(handle->curr_output_line * handle->char_width + handle->curr_output_col);
537                 memset((void *)(&handle->buffer[index]), 0x20, sizeof(u8) * handle->char_width);
538 
539             }
540             else
541             {
542                 index = (u16)(handle->curr_output_line * handle->char_width + handle->curr_output_col);
543                 handle->buffer[index] = (u8)buffer[i];
544                 handle->curr_output_col++;
545             }
546 
547             if (handle->curr_output_col >= handle->char_width)
548             {
549                 handle->curr_output_col = 0;
550                 handle->curr_output_line = (u16)((handle->curr_output_line + 1) % handle->total_lines);
551                 handle->curr_view_line   = (u16)((handle->curr_view_line + 1) % handle->total_lines);
552 
553                 // Clobber new output line
554                 index = (u16)(handle->curr_output_line * handle->char_width + handle->curr_output_col);
555                 memset((void *)(&handle->buffer[index]), 0x20, sizeof(u8) * handle->char_width);
556 
557             }
558         }
559 
560         OSRestoreInterrupts(old);
561 
562 } // End DEMOWinLogPrintf()
563 
564 /*---------------------------------------------------------------------------*
565  * Name        : DEMOWinPrintfXY()
566  *
567  * Description :
568  *
569  * Arguments   : None.
570  *
571  * Returns     : None.
572  *
573  *---------------------------------------------------------------------------*/
DEMOWinPrintfXY(DEMOWinInfo * handle,u16 col,u16 row,char * fmt,...)574 void DEMOWinPrintfXY(DEMOWinInfo *handle, u16 col, u16 row, char *fmt, ...)
575 {
576 
577     BOOL old;
578 
579     va_list vlist;
580     char    string[DEMOWIN_MAX_STRING_SIZE];
581 
582     u16     buffer_row; // Map window row-coord to buffer space
583     u16     i;
584     u16     index;
585 
586 
587         // If row/col coords are outside of the window, then don't bother
588         if ((row >= handle->char_height) || (col >= handle->char_width))
589         {
590             return;
591         }
592 
593         old = OSDisableInterrupts();
594 
595         // Get output string
596         va_start(vlist, fmt);
597         vsprintf(string, fmt, vlist);
598         va_end(vlist);
599 
600         // Find top line of window in buffer
601         buffer_row = (u16)(  ((handle->curr_view_line + handle->total_lines) - (handle->char_height-1)) % handle->total_lines);
602 
603         // Now descend through buffer until we get the desired row
604         buffer_row = (u16)((buffer_row + row) % handle->total_lines);
605         // Truncate string to right-hand screen edge
606         string[handle->char_width - col] = 0;
607 
608         index = (u16)(buffer_row * handle->char_width + col);
609 
610         for (i=0; i<strlen(string); i++)
611         {
612             handle->buffer[index+i] = (u8)string[i];
613         }
614 
615         OSRestoreInterrupts(old);
616 
617 
618 } // End DEMOWinLogPrintf()
619 
620 /*---------------------------------------------------------------------------*
621  * Name        : DEMOWinScroll()
622  *
623  * Description : Scrolls ONE line up or down.
624  *
625  * Arguments   : None.
626  *
627  * Returns     : None.
628  *
629  *---------------------------------------------------------------------------*/
DEMOWinScrollWindow(DEMOWinInfo * handle,u32 dir)630 void DEMOWinScrollWindow(DEMOWinInfo *handle, u32 dir)
631 {
632 
633     BOOL old;
634 
635     u16  n;
636     u16  v_start;
637 
638 
639         ASSERTMSG(handle, "DEMOWinScrollWindow(): NULL handle!\n");
640         ASSERTMSG(handle->num_scroll_lines, "DEMOWinScrollWindow(): No scrollback buffer!\n");
641 
642 
643         switch(dir)
644         {
645             case DEMOWIN_SCROLL_UP:
646                 old = OSDisableInterrupts();
647 
648                 n = (u16)(((handle->curr_view_line + handle->total_lines) - 1) % handle->total_lines);
649 
650                 v_start = (u16)(((n + handle->total_lines) - handle->char_height+1) % handle->total_lines);
651 
652                 if (v_start != handle->curr_output_line)
653                 {
654                     handle->curr_view_line = n;
655                 }
656                 OSRestoreInterrupts(old);
657                 break;
658 
659             case DEMOWIN_SCROLL_DOWN:
660                 old = OSDisableInterrupts();
661                 if (handle->curr_view_line != handle->curr_output_line)
662                 {
663                     handle->curr_view_line = (u16)((handle->curr_view_line + 1) % handle->total_lines);
664                 }
665                 OSRestoreInterrupts(old);
666                 break;
667 
668             case DEMOWIN_SCROLL_HOME:
669                 old = OSDisableInterrupts();
670                 handle->curr_view_line = handle->curr_output_line;
671                 OSRestoreInterrupts(old);
672                 break;
673 
674             default:
675                 ASSERTMSG(0, "DEMOWinScrollWindow(): Unknown token\n");
676                 break;
677 
678         } // End switch
679 
680 
681 } // End DEMOWinScrollWindow
682 
683 
684 /*---------------------------------------------------------------------------*
685  * Name        : DEMOWinBringToFront()
686  *
687  * Description :
688  *
689  * Arguments   : None.
690  *
691  * Returns     : None.
692  *
693  *---------------------------------------------------------------------------*/
DEMOWinBringToFront(DEMOWinInfo * handle)694 void DEMOWinBringToFront(DEMOWinInfo *handle)
695 {
696     DEMOWinInfo *ptr;
697 
698         ASSERTMSG(__first_node, "DEMOWinBringToFront(): Window list is empty!\n");
699         ASSERTMSG(handle, "DEMOWinBringToFront(): NULL handle!\n");
700 
701         if (DEMOWIN_PRIORITY_FORE == handle->priority)
702         {
703             return;
704         }
705 
706         // Send everyone else to the background
707         ptr = __first_node;
708         while (ptr)
709         {
710             ptr->priority = DEMOWIN_PRIORITY_BACK;
711             ptr = ptr->next;
712         }
713 
714         // Bring our window to the front
715         handle->priority = DEMOWIN_PRIORITY_FORE;
716 
717 
718 
719 } // End DEMOWinBringToFront()
720 
721 /*---------------------------------------------------------------------------*
722  * Name        : DEMOWinSendToBack()
723  *
724  * Description :
725  *
726  * Arguments   : None.
727  *
728  * Returns     : None.
729  *
730  *---------------------------------------------------------------------------*/
DEMOWinSendToBack(DEMOWinInfo * handle)731 void DEMOWinSendToBack(DEMOWinInfo *handle)
732 {
733 
734     ASSERTMSG(handle, "DEMOWinSendToBack(): NULL handle!\n");
735     handle->priority = DEMOWIN_PRIORITY_BACK;
736 
737 } // End DEMOWinSendToBack()
738 
739 
740 /*---------------------------------------------------------------------------*
741  * Name        : DEMOWinClearRow()
742  *
743  * Description :
744  *
745  * Arguments   : None.
746  *
747  * Returns     : None.
748  *
749  *---------------------------------------------------------------------------*/
DEMOWinClearRow(DEMOWinInfo * handle,u16 row)750 void DEMOWinClearRow(DEMOWinInfo *handle, u16 row)
751 {
752 
753     u16  buffer_row;
754     u16  index;
755     u16  i;
756     BOOL old;
757 
758         ASSERTMSG(handle, "DEMOWinClearRow(): NULL handle!\n");
759 
760 
761         // Bail if the row is outside the window
762         if (row >= handle->char_height)
763         {
764             return;
765         }
766 
767         old = OSDisableInterrupts();
768 
769         // Find top line of window in buffer
770         buffer_row = (u16)(  ((handle->curr_view_line + handle->total_lines) - (handle->char_height-1)) % handle->total_lines);
771 
772         // Now descend through buffer until we get the desired row
773         buffer_row = (u16)((buffer_row + row) % handle->total_lines);
774 
775         index = (u16)(buffer_row * handle->char_width);
776 
777         for (i=0; i<handle->char_width; i++)
778         {
779             handle->buffer[index+i] = 0x20;
780         }
781 
782         OSRestoreInterrupts(old);
783 
784 
785 
786 
787 } // End DEMOWinClearRow()
788 
789 /*---------------------------------------------------------------------------*
790  * Name        : DEMOWinClearWindow()
791  *
792  * Description :
793  *
794  * Arguments   : None.
795  *
796  * Returns     : None.
797  *
798  *---------------------------------------------------------------------------*/
DEMOWinClearWindow(DEMOWinInfo * handle)799 void DEMOWinClearWindow(DEMOWinInfo *handle)
800 {
801 
802     u16  buffer_row;
803     u16  index;
804     u16  i;
805     BOOL old;
806 
807         ASSERTMSG(handle, "DEMOWinClearWindow(): NULL handle!\n");
808 
809 
810         old = OSDisableInterrupts();
811 
812         // find top line of window in buffer
813         buffer_row = (u16)(  ((handle->curr_view_line + handle->total_lines) - (handle->char_height-1)) % handle->total_lines);
814 
815         for (i=0; i<handle->char_height; i++)
816         {
817             index = (u16)(buffer_row * handle->char_width);
818             memset((void *)(&handle->buffer[index]), 0x20, sizeof(u8) * handle->char_width);
819             buffer_row = (u16)((buffer_row + 1) % handle->total_lines);
820         }
821 
822         OSRestoreInterrupts(old);
823 
824 } // End DEMOWinClearWindow()
825 
826 
827 /*---------------------------------------------------------------------------*
828  * Name        : DEMOWinClearBuffer()
829  *
830  * Description :
831  *
832  * Arguments   : None.
833  *
834  * Returns     : None.
835  *
836  *---------------------------------------------------------------------------*/
DEMOWinClearBuffer(DEMOWinInfo * handle)837 void DEMOWinClearBuffer(DEMOWinInfo *handle)
838 {
839     BOOL old;
840 
841         ASSERTMSG(handle, "DEMOWinClearBuffer(): NULL handle!\n");
842 
843         old = OSDisableInterrupts();
844 
845         memset(handle->buffer, 0x20, sizeof(u8) * handle->total_lines * handle->char_width);
846 
847 
848         OSRestoreInterrupts(old);
849 
850 } // End DEMOWinClearBuffer()
851 
852 
853 
854 
855 
856 
857 
858 /*---------------------------------------------------------------------------*
859  * Name        : DEMOWinRefresh()
860  *
861  * Description :
862  *
863  * Arguments   : None.
864  *
865  * Returns     : None.
866  *
867  *---------------------------------------------------------------------------*/
DEMOWinRefresh(void)868 void DEMOWinRefresh(void)
869 {
870 
871     DEMOWinInfo *ptr;
872 
873     u16 i;
874     u16 index;
875     u16 n;
876 
877     u16 y;
878 
879     BOOL old;
880 
881         ASSERTMSG(__first_node, "DEMOWinRefresh(): Windowlist is empty!\n");
882 
883         ptr = __first_node;
884 
885         while(ptr)
886         {
887 
888 
889             if (ptr->flags & DEMOWIN_FLAG_VISIBLE)
890             {
891 
892                 // ------------------------------------------------------------
893                 // DRAW WINDOWS FIRST - they are drawn without alpha/blending
894                 // ------------------------------------------------------------
895 
896                 // Windows
897                 GXSetZMode( GX_ENABLE, GX_LEQUAL, GX_ENABLE );
898                 GXSetBlendMode(GX_BM_BLEND, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR);
899 
900                 // Set vertex descriptor
901                 GXClearVtxDesc();
902                 GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
903                 GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
904 
905                 // Position has 3 elements (x,y,z), each of a float type
906                 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
907                 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
908 
909                 // Disable lighting
910                 GXSetNumChans(1);
911                 GXSetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );
912 
913                 // One tevstage that passes color
914                 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
915                 GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
916                 GXSetNumTexGens(0);
917                 GXSetNumTevStages(1);
918 
919                 GXSetLineWidth( 6, GX_TO_ZERO );
920 
921                 // Window background
922                 GXBegin(GX_QUADS, GX_VTXFMT0, 4);
923                     GXPosition3f32(ptr->x1, ptr->y1, (f32)(ptr->priority));
924                     GXColor4u8( ptr->bkgnd.r, ptr->bkgnd.g, ptr->bkgnd.b, ptr->bkgnd.a );
925 
926                     GXPosition3f32(ptr->x2, ptr->y1, (f32)(ptr->priority));
927                     GXColor4u8( ptr->bkgnd.r, ptr->bkgnd.g, ptr->bkgnd.b, ptr->bkgnd.a );
928 
929                     GXPosition3f32(ptr->x2, ptr->y2, (f32)(ptr->priority));
930                     GXColor4u8( ptr->bkgnd.r, ptr->bkgnd.g, ptr->bkgnd.b, ptr->bkgnd.a );
931 
932                     GXPosition3f32(ptr->x1, ptr->y2, (f32)(ptr->priority));
933                     GXColor4u8( ptr->bkgnd.r, ptr->bkgnd.g, ptr->bkgnd.b, ptr->bkgnd.a );
934                 GXEnd();
935 
936 
937                 // caption
938                 GXSetBlendMode(GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR);
939                 GXBegin(GX_QUADS, GX_VTXFMT0, 4);
940                     GXPosition3f32(ptr->x1, ptr->y1, (f32)(ptr->priority));
941                     GXColor4u8( ptr->cap.r, ptr->cap.g, ptr->cap.b, 0xff );
942 
943                     GXPosition3f32(ptr->x2, ptr->y1, (f32)(ptr->priority));
944                     GXColor4u8( 0, 0, 0, 64 );
945 
946                     GXPosition3f32(ptr->x2, ptr->y1+FONT_CHAR_HEIGHT+2, (f32)(ptr->priority));
947                     GXColor4u8( 0, 0, 0, 64 );
948 
949                     GXPosition3f32(ptr->x1, ptr->y1+FONT_CHAR_HEIGHT+2, (f32)(ptr->priority));
950                     GXColor4u8( ptr->cap.r, ptr->cap.g, ptr->cap.b, 0xff );
951                 GXEnd();
952 
953                 // border
954                 GXSetBlendMode(GX_BM_BLEND, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR);
955                 {
956                     u8 r1,g1,b1;
957                     u8 r2,g2,b2;
958                     u8 a;
959 
960                         r1 = (u8)((f32)(ptr->border.r)*1.3);
961                         g1 = (u8)((f32)(ptr->border.g)*1.3);
962                         b1 = (u8)((f32)(ptr->border.b)*1.3);
963 
964                         r2 = (u8)((f32)(ptr->border.r)*0.40);
965                         g2 = (u8)((f32)(ptr->border.g)*0.40);
966                         b2 = (u8)((f32)(ptr->border.b)*0.40);
967 
968                         a  = 0x40;
969 
970                         GXSetLineWidth( 6, GX_TO_ZERO );
971                         GXBegin(GX_LINESTRIP, GX_VTXFMT0, 7);
972                             GXPosition3f32(ptr->x1, ptr->y1, (f32)(ptr->priority));
973                             GXColor4u8(r1, g1, b1, a);
974 
975                             GXPosition3f32(ptr->x2, ptr->y1, (f32)(ptr->priority));
976                             GXColor4u8(r1, g1, b1, a);
977 
978                             GXPosition3f32(ptr->x2, ptr->y1, (f32)(ptr->priority));
979                             GXColor4u8(r2, g2, b2, a);
980 
981                             GXPosition3f32(ptr->x2, ptr->y2, (f32)(ptr->priority));
982                             GXColor4u8(r2, g2, b2, a);
983 
984                             GXPosition3f32(ptr->x1, ptr->y2, (f32)(ptr->priority));
985                             GXColor4u8(r2, g2, b2, a);
986 
987                             GXPosition3f32(ptr->x1, ptr->y2, (f32)(ptr->priority));
988                             GXColor4u8(r1, g1, b1, a);
989 
990                             GXPosition3f32(ptr->x1, ptr->y1, (f32)(ptr->priority));
991                             GXColor4u8(r1, g1, b1, a);
992                         GXEnd();
993 
994                 }
995 
996                 // Invoke user refresh callback
997                 if (ptr->refresh)
998                 {
999                     // Invoke refresh callback
1000                     // User refresh should be invoked before application of caption/title and cursor highlighting, if any
1001                     (*(ptr->refresh))(ptr);
1002                 }
1003 
1004                 // ------------------------------------------------------------
1005                 // Now slap on the text
1006                 // ------------------------------------------------------------
1007                 DEMOInitCaption(DM_FT_XLU, __rmp->fbWidth, __rmp->efbHeight);
1008                 GXSetZMode( GX_ENABLE, GX_LEQUAL, GX_ENABLE );
1009 
1010                 old = OSDisableInterrupts();
1011 
1012                 n = ptr->curr_view_line;
1013 
1014                 y     = (u16)(ptr->y2 - FONT_CHAR_HEIGHT - ptr->y_cal);
1015                 n     = (u16)(ptr->curr_view_line);
1016                 index = (u16)(n * ptr->char_width);
1017 
1018                 for (i=0; i<ptr->char_height; i++)
1019                 {
1020 
1021                     __DEMOWin_puts_n((s16)(ptr->x1+ptr->x_cal), (s16)y, (s16)ptr->priority, ptr->char_width, (char *)(&ptr->buffer[index]));
1022 
1023                     y = (u16)(y - FONT_CHAR_HEIGHT);                               // Decrement y-coord
1024                     n = (u16)((((n + ptr->total_lines) - 1) % ptr->total_lines));  // Decrement current view line
1025                     index = (u16)(n * ptr->char_width);                            // Recalc index
1026                 }
1027 
1028                 DEMOPrintf((s16)(ptr->x1+2), (s16)ptr->y1, (s16)ptr->priority, "%s", ptr->caption);
1029 
1030                 // ------------------------------------------------------------
1031                 // Now add highlighting, if any
1032                 // ------------------------------------------------------------
1033                 if (ptr->cursor_line >= 0)
1034                 {
1035 
1036                     GXSetLineWidth( 6, GX_TO_ZERO );
1037 
1038                     GXSetZMode( GX_ENABLE, GX_LEQUAL, GX_ENABLE );
1039                     GXSetBlendMode(GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR);
1040 
1041                     // Set vertex descriptor
1042                     GXClearVtxDesc();
1043                     GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
1044                     GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
1045 
1046                     // Position has 3 elements (x,y,z), each of a float type
1047                     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
1048                     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
1049 
1050                     // Disable lighting
1051                     GXSetNumChans(1);
1052                     GXSetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );
1053 
1054                     // One tevstage that passes color
1055                     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
1056                     GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
1057                     GXSetNumTexGens(0);
1058                     GXSetNumTevStages(1);
1059 
1060 
1061                     GXSetLineWidth( 6, GX_TO_ZERO );
1062                     {
1063                         u8  r;
1064                         u8  g;
1065                         u8  b;
1066                         u8  a;
1067                         s32 curr_y;
1068 
1069 
1070                         curr_y = ptr->y2 - FONT_CHAR_HEIGHT - ptr->y_cal;
1071                         curr_y = curr_y - ( ((ptr->char_height-1)*FONT_CHAR_HEIGHT) - ((ptr->cursor_line)*FONT_CHAR_HEIGHT));
1072 
1073                         r = (u8)((f32)(ptr->bkgnd.r) * 1.9);
1074                         g = (u8)((f32)(ptr->bkgnd.g) * 1.9);
1075                         b = (u8)((f32)(ptr->bkgnd.b) * 1.9);
1076                         a = 0x64;
1077 
1078                         GXBegin(GX_QUADS, GX_VTXFMT0, 4);
1079                             GXPosition3f32( (f32)(ptr->x1), (f32)(curr_y), (f32)(ptr->priority));
1080                             GXColor4u8(r,g,b,a);
1081 
1082                             GXPosition3f32( (f32)(ptr->x2), (f32)(curr_y), (f32)(ptr->priority));
1083                             GXColor4u8(r,g,b,a);
1084 
1085                             GXPosition3f32( (f32)(ptr->x2), (f32)(curr_y+FONT_CHAR_HEIGHT), (f32)(ptr->priority));
1086                             GXColor4u8(r,g,b,a);
1087 
1088                             GXPosition3f32( (f32)(ptr->x1), (f32)(curr_y+FONT_CHAR_HEIGHT), (f32)(ptr->priority));
1089                             GXColor4u8(r,g,b,a);
1090                         GXEnd();
1091                     }
1092                 }
1093 
1094                 OSRestoreInterrupts(old);
1095 
1096             } // if visible
1097 
1098             ptr = ptr->next;
1099 
1100         } // End while...
1101 
1102 
1103 
1104 } // End DEMOWinRefresh()
1105 
1106 
1107 
1108 /*---------------------------------------------------------------------------*
1109  * Name        : __DEMOWinadd_node()
1110  *
1111  * Description :
1112  *
1113  * Arguments   : None.
1114  *
1115  * Returns     : None.
1116  *
1117  *---------------------------------------------------------------------------*/
__DEMOWin_add_node(DEMOWinInfo * handle)1118 static void __DEMOWin_add_node(DEMOWinInfo *handle)
1119 {
1120 
1121     ASSERTMSG(handle, "__add_node(): you're adding a NULL node!\n");
1122 
1123     if (NULL == __last_node)
1124     {
1125         // We're the first node!
1126         __first_node = __last_node = __curr_node = handle;
1127 
1128         handle->next = NULL;
1129         handle->prev = NULL;
1130 
1131         ASSERTMSG(__first_node, "  > __first_node: NULL HANDLE!\n");
1132     }
1133     else
1134     {
1135 
1136         __last_node->next = handle;
1137         handle->next = NULL;
1138         handle->prev = __last_node;
1139         __last_node = handle;
1140     }
1141 
1142     handle->flags |= DEMOWIN_FLAG_ATTACHED;
1143 
1144 } // add_node()
1145 
1146 
1147 /*---------------------------------------------------------------------------*
1148  * Name        : __DEMOWin__delete_node()
1149  *
1150  * Description :
1151  *
1152  * Arguments   : None.
1153  *
1154  * Returns     : None.
1155  *
1156  *---------------------------------------------------------------------------*/
__DEMOWin_delete_node(DEMOWinInfo * handle)1157 static void __DEMOWin_delete_node(DEMOWinInfo *handle)
1158 {
1159 
1160     ASSERTMSG(handle, "__delete_node(): you're deleting a NULL node!\n");
1161 
1162 
1163     // It's the first node
1164     if (__first_node == handle)
1165     {
1166         // Does a next node even exist?
1167         if (handle->next)
1168         {
1169             __first_node = (handle->next);
1170             (handle->next)->prev = NULL;
1171         }
1172         else
1173         {
1174             // Nope it must have been the only node in the universe
1175             __first_node = __last_node = NULL;
1176         }
1177 
1178     }
1179     else if (__last_node == handle)
1180     {
1181         // Does a previous node even exist?
1182         if (handle->prev)
1183         {
1184             // Yes
1185             __last_node = (handle->prev);
1186             (handle->prev)->next = NULL;
1187 
1188         }
1189         else
1190         {
1191             // Nope, it was the only node in the universe
1192             __first_node = __last_node = NULL;
1193         }
1194 
1195     }
1196     else
1197     {
1198         (handle->prev)->next = (handle->next);
1199         (handle->next)->prev = (handle->prev);
1200 
1201     }
1202 
1203     handle->flags = (handle->flags & (~DEMOWIN_FLAG_ATTACHED));
1204 
1205 
1206 } // add_node()
1207 
1208 
1209 /*---------------------------------------------------------------------------*
1210  * Name        : __DEMOWin_puts_n()
1211  *
1212  * Description : Writes specified number of characters in string to screen
1213  *
1214  * Arguments   :
1215  *
1216  * Returns     :
1217  *
1218  *---------------------------------------------------------------------------*/
__DEMOWin_puts_n(s16 x,s16 y,s16 z,u16 n,char * string)1219 static void __DEMOWin_puts_n( s16 x, s16 y, s16 z, u16 n, char* string )
1220 {
1221     s32   s, t;
1222     s32   w, len, i;
1223 
1224         // Set up vertex descriptors
1225         GXClearVtxDesc();
1226         GXSetVtxDesc( GX_VA_POS,  GX_DIRECT );
1227         GXSetVtxDesc( GX_VA_TEX0, GX_DIRECT );
1228         GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_POS,  GX_POS_XYZ, GX_S16, 0 );
1229         GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST,  GX_S16, 1 );
1230 
1231         len = n;
1232 
1233         if ( len > 0 )
1234         {
1235             // Put a line
1236             GXBegin( GX_QUADS, GX_VTXFMT0, (u16)(len*4) );
1237             for ( i = 0; i < len; i ++ )
1238             {
1239                 // Draw a letter
1240                 w = string[i] - ' ';
1241                 s = ( w % 8 ) * 16 + fontShift;
1242                 t = ( w / 8 ) * 16 + fontShift;
1243                 GXPosition3s16( (s16)(i*8+x  ), (s16)(y   ), z );
1244                 GXTexCoord2s16( (s16)(s      ), (s16)(t   )    );
1245                 GXPosition3s16( (s16)(i*8+x+8), (s16)(y   ), z );
1246                 GXTexCoord2s16( (s16)(s+16   ), (s16)(t   )    );
1247                 GXPosition3s16( (s16)(i*8+x+8), (s16)(y+8 ), z );
1248                 GXTexCoord2s16( (s16)(s+16   ), (s16)(t+16)    );
1249                 GXPosition3s16( (s16)(i*8+x  ), (s16)(y+8 ), z );
1250                 GXTexCoord2s16( (s16)(s      ), (s16)(t+16)    );
1251             }
1252             GXEnd( );
1253         }
1254 
1255 } // End __DEMOWinPutsN()
1256 
1257 
1258 //****************************************************************************
1259 // Menu Stuff
1260 //****************************************************************************
1261 
1262 /*---------------------------------------------------------------------------*
1263  * Name        : DEMOWinCreateMenuWindow()
1264  *
1265  * Description : Obvious
1266  *
1267  * Arguments   : None.
1268  *
1269  * Returns     : None.
1270  *
1271  *---------------------------------------------------------------------------*/
1272 
DEMOWinCreateMenuWindow(DEMOWinMenuInfo * menu,u16 x,u16 y)1273 DEMOWinMenuInfo *DEMOWinCreateMenuWindow(DEMOWinMenuInfo *menu, u16 x, u16 y)
1274 {
1275 
1276     DEMOWinMenuItem *ptr;
1277 
1278         // Calculate max name/title string length
1279         // Calculate number of items in list
1280         ptr = menu->items;
1281 
1282         menu->max_str_len = strlen(menu->title);
1283         menu->num_items   = 0;
1284 
1285         while (!(ptr->flags & DEMOWIN_ITM_TERMINATOR))
1286         {
1287             if (strlen(ptr->name) > menu->max_str_len)
1288             {
1289                 menu->max_str_len = strlen(ptr->name);
1290             }
1291             (menu->num_items)++;
1292             ptr++;
1293         }
1294 
1295         // Calculate actual number of items to display
1296         // It may be less than the max number specified by the user
1297         if (menu->num_items > menu->max_display_items)
1298         {
1299             menu->num_display_items = menu->max_display_items;
1300         }
1301         else
1302         {
1303             menu->num_display_items = menu->num_items;
1304         }
1305 
1306         // Open window.
1307         // Note: this call will ASSERT if it fails to allocate a window
1308         menu->handle = DEMOWinCreateWindow((s16)x,
1309                                            (s16)y,
1310                                            (s16)(x + DEMOWIN_CALC_MENU_WIDTH_PIXELS(menu->max_str_len)),
1311                                            (s16)(y + DEMOWIN_CALC_MENU_HEIGHT_PIXELS(menu->num_display_items)),
1312                                             menu->title,
1313                                             0,              // No scrollback lines! Menu function handles list scrolling
1314                                             __DEMOWinMenu_refesh_menu);
1315 
1316 
1317         // Parent of this window is the "menu" structure
1318         (menu->handle)->parent = menu;
1319 
1320 
1321 
1322         if (menu->num_items)
1323         {
1324             return(menu);
1325         }
1326 
1327         return(NULL);
1328 
1329 
1330 } // End DEMOWinCreateMenuWindow()
1331 
1332 
1333 /*---------------------------------------------------------------------------*
1334  * Name        : DEMOWinDestroyMenuWindow()
1335  *
1336  * Description : Obvious
1337  *
1338  * Arguments   : None.
1339  *
1340  * Returns     : None.
1341  *
1342  *---------------------------------------------------------------------------*/
1343 
DEMOWinDestroyMenuWindow(DEMOWinMenuInfo * menu)1344 void DEMOWinDestroyMenuWindow(DEMOWinMenuInfo *menu)
1345 {
1346 
1347     if (menu->handle)
1348     {
1349         DEMOWinCloseWindow(menu->handle);
1350         DEMOWinDestroyWindow(menu->handle);
1351 
1352         menu->handle = NULL;
1353     }
1354 
1355 } // End DEMOWinDestroyMenuWindow()
1356 
1357   /*---------------------------------------------------------------------------*
1358  * Name        : DEMOWinMenuChild()
1359  *
1360  * Description : Obvious
1361  *
1362  * Arguments   : None.
1363  *
1364  * Returns     : None.
1365  *
1366  *---------------------------------------------------------------------------*/
1367 
DEMOWinMenuChild(DEMOWinMenuInfo * menu,BOOL child_flag)1368 u32 DEMOWinMenuChild(DEMOWinMenuInfo *menu, BOOL child_flag)
1369 {
1370 
1371     DEMOWinPadInfo  *pad;           // Pointer to pad data associated with this menu's window
1372     DEMOWinInfo     *handle;        // Pointer to window associated with this menu
1373 
1374     u16  user_input;                // User input from PAD
1375     BOOL exit_flag = FALSE;
1376     u32  result = 0;
1377 
1378 
1379 
1380         // This is cheesy but...
1381         handle = menu->handle;
1382         pad    = &(menu->handle)->pad;
1383 
1384 
1385         // Display window, bring to foreground
1386         DEMOWinOpenWindow(handle);
1387         DEMOWinBringToFront(handle);
1388 
1389 
1390         // Initialize cursor and display-position state
1391         menu->curr_pos    = 0;
1392         menu->display_pos = 0;
1393 
1394         // Is there a callback for "open" event?
1395         if (menu->cb_open)
1396         {
1397             (*menu->cb_open)(menu, (u32)menu->curr_pos);
1398         }
1399 
1400 
1401         // debounce
1402         DEMOWinPadInit(pad);
1403 
1404         DEMOBeforeRender();
1405         DEMOWinRefresh();
1406         DEMODoneRender();
1407 
1408         DEMOWinPadRead(pad);
1409 
1410         DEMOBeforeRender();
1411         DEMOWinRefresh();
1412         DEMODoneRender();
1413 
1414 
1415         while(!exit_flag)
1416         {
1417 
1418             user_input = __DEMOWinMenu_get_user_input(pad);
1419 
1420             switch(user_input)
1421             {
1422                 case DEMOWIN_MNU_UP:
1423 
1424                     menu->curr_pos = (u16)((menu->curr_pos - 1 + menu->num_items) % (menu->num_items));
1425                     while( (menu->items[menu->curr_pos].flags & (DEMOWIN_ITM_DISABLED | DEMOWIN_ITM_SEPARATOR)) )
1426                     {
1427                         menu->curr_pos = (u16)((menu->curr_pos - 1 + menu->num_items) % (menu->num_items));
1428                     }
1429                     if (menu->cb_move)
1430                     {
1431                         (*(menu->cb_move))(menu, (u32)menu->curr_pos);
1432                     }
1433 
1434                     break;
1435 
1436                 case DEMOWIN_MNU_DOWN:
1437                     menu->curr_pos = (u16)((menu->curr_pos + 1) % (menu->num_items));
1438                     while ((menu->items[menu->curr_pos].flags & (DEMOWIN_ITM_DISABLED | DEMOWIN_ITM_SEPARATOR)))
1439                     {
1440                         menu->curr_pos = (u16)((menu->curr_pos + 1) % (menu->num_items));
1441                     }
1442                     if (menu->cb_move)
1443                     {
1444                         (*(menu->cb_move))(menu, (u32)menu->curr_pos);
1445                     }
1446 
1447                     break;
1448 
1449                 case DEMOWIN_MNU_LEFT:
1450                     if (TRUE == child_flag)
1451                     {
1452                         // We are a child of another popup menu.
1453                         exit_flag = TRUE;
1454                         if (menu->cb_cancel)
1455                         {
1456                             (*(menu->cb_cancel))(menu, (u32)menu->curr_pos);
1457                         }
1458 
1459                     }
1460                     break;
1461 
1462                 case DEMOWIN_MNU_RIGHT:
1463                     // Callback?
1464                     if (menu->cb_move)
1465                     {
1466                         (*(menu->cb_move))(menu, (u32)menu->curr_pos);
1467                     }
1468 
1469 
1470                     // Ugh. Now, is there a link?
1471                     if (menu->items[menu->curr_pos].link)
1472                     {
1473                         // Yes, there's a link. Is there an associated window handle?
1474                         if ((menu->items[menu->curr_pos].link)->handle)
1475                         {
1476                             // Yup! So replace the window coordinates...
1477                             ((menu->items[menu->curr_pos].link)->handle)->x1 = (u16)(handle->x1 + 20);
1478                             ((menu->items[menu->curr_pos].link)->handle)->y1 = (u16)(handle->y1 + 20);
1479 
1480                             // ...and invoke the menu
1481                             result = DEMOWinMenuChild(menu->items[menu->curr_pos].link, TRUE);
1482                             if ((menu->items[menu->curr_pos].link)->flags & DEMOWIN_MNU_EOM)
1483                             {
1484                                 exit_flag=TRUE;
1485                             }
1486 
1487                         }
1488                         else
1489                         {
1490                             // Nope. No window handle. So...create one!
1491                             DEMOWinCreateMenuWindow(menu->items[menu->curr_pos].link, (u16)(handle->x1+20), (u16)(handle->y1+20));
1492                             result = DEMOWinMenuChild(menu->items[menu->curr_pos].link, TRUE);
1493                             if ((menu->items[menu->curr_pos].link)->flags & DEMOWIN_MNU_EOM)
1494                             {
1495                                 exit_flag=TRUE;
1496                             }
1497                             DEMOWinDestroyMenuWindow(menu->items[menu->curr_pos].link);
1498 
1499                         }
1500                         VIWaitForRetrace();
1501                         DEMOWinPadRead(pad);
1502 
1503                     }
1504 
1505                     break;
1506 
1507                 case DEMOWIN_MNU_SELECT:
1508                     if (menu->cb_select)
1509                     {
1510                         (*(menu->cb_select))(menu, (u32)menu->curr_pos);
1511                     }
1512 
1513                     if (menu->items[menu->curr_pos].link)
1514                     {
1515                         // Yes, there's a link. Is there an associated window handle?
1516                         if ((menu->items[menu->curr_pos].link)->handle)
1517                         {
1518                             // Yup! So replace the window coordinates...
1519                             ((menu->items[menu->curr_pos].link)->handle)->x1 = (u16)(handle->x1 + 20);
1520                             ((menu->items[menu->curr_pos].link)->handle)->y1 = (u16)(handle->y1 + 20);
1521 
1522                             // ...and invoke the menu
1523                             result = DEMOWinMenuChild(menu->items[menu->curr_pos].link, TRUE);
1524                             if ((menu->items[menu->curr_pos].link)->flags & DEMOWIN_MNU_EOM)
1525                             {
1526                                 exit_flag=TRUE;
1527                             }
1528 
1529                         }
1530                         else
1531                         {
1532                             // Nope. No window handle. So...create one!
1533                             DEMOWinCreateMenuWindow(menu->items[menu->curr_pos].link, (u16)(handle->x1+20), (u16)(handle->y1+20));
1534 
1535                             // ...and invoke the menu
1536                             result = DEMOWinMenuChild(menu->items[menu->curr_pos].link, TRUE);
1537 
1538 
1539                             // Now...should we kill the parent on this link?
1540                             if ((menu->items[menu->curr_pos].link)->flags & DEMOWIN_MNU_EOM)
1541                             {
1542                                 exit_flag=TRUE;
1543                             }
1544                             DEMOWinDestroyMenuWindow(menu->items[menu->curr_pos].link);
1545 
1546 
1547 
1548                         }
1549                         VIWaitForRetrace();
1550                         DEMOWinPadRead(pad);
1551 
1552                     }
1553                     else
1554                     {
1555                         if (menu->items[menu->curr_pos].function)
1556                         {
1557                             (menu->items[menu->curr_pos].function)(menu, (u32)menu->curr_pos, &result);
1558                             if (menu->items[menu->curr_pos].flags & DEMOWIN_ITM_EOF)
1559                             {
1560                                 exit_flag = TRUE;
1561                             }
1562                             VIWaitForRetrace();
1563                             DEMOWinPadRead(pad);
1564 
1565                         }
1566 
1567                     }
1568                     break;
1569 
1570                 case DEMOWIN_MNU_CANCEL:
1571                     if (menu->cb_cancel)
1572                     {
1573                         (*(menu->cb_cancel))(menu, (u32)menu->curr_pos);
1574                     }
1575                     exit_flag = TRUE;
1576                     break;
1577 
1578             }// End switch(parse_input)
1579 
1580 
1581             // Fix display pointer
1582             if (menu->curr_pos > (menu->display_pos+menu->num_display_items-1))
1583             {
1584                 menu->display_pos = menu->curr_pos - menu->num_display_items + 1;
1585 
1586             }
1587             else if (menu->curr_pos < menu->display_pos)
1588             {
1589                 menu->display_pos = menu->curr_pos;
1590             }
1591 
1592             // Calculate cursor position
1593             if (menu->display_pos > menu->curr_pos)
1594             {
1595                 handle->cursor_line = (s16)(menu->display_pos - menu->curr_pos);
1596             }
1597             else
1598             {
1599                 handle->cursor_line = (s16)(menu->curr_pos - menu->display_pos);
1600             }
1601 
1602 
1603             DEMOBeforeRender();
1604             DEMOWinRefresh();
1605             DEMODoneRender();
1606 
1607 
1608         } // While exit
1609 
1610 
1611         DEMOWinCloseWindow(handle);
1612 
1613         DEMOBeforeRender();
1614         DEMOWinRefresh();
1615         DEMODoneRender();
1616 
1617 
1618         return(result);
1619 
1620 
1621 } // End DEMOWinMenuChild()
1622 
1623 /*---------------------------------------------------------------------------*
1624  * Name        : __DEMOWinMenu_display_menu()
1625  *
1626  * Description : Obvious
1627  *
1628  * Arguments   : None.
1629  *
1630  * Returns     : None.
1631  *
1632  *---------------------------------------------------------------------------*/
1633 
__DEMOWinMenu_refesh_menu(DEMOWinInfo * w)1634 static void __DEMOWinMenu_refesh_menu(DEMOWinInfo *w)
1635 {
1636 
1637     DEMOWinMenuInfo *m;
1638 
1639     s32  i;
1640     s32  j;
1641     char check;
1642     char para_start;
1643     char para_end;
1644     char link;
1645 
1646 
1647         // Clear window contents
1648         DEMOWinClearWindow(w);
1649 
1650         // Parent should be a Menu info structure
1651         m = (w->parent);
1652 
1653         j = m->display_pos;
1654 
1655         for (i=0; i<m->num_display_items; i++)
1656         {
1657             if (m->items[j].flags & DEMOWIN_ITM_SEPARATOR)
1658             {
1659 
1660                 if (strlen(m->items[(u16)j].name))
1661                 {
1662                     DEMOWinPrintfXY(w, 0, (u16)i, "   %s     ", m->items[(u16)j].name);
1663                 }
1664 
1665             }
1666             else
1667             {
1668 
1669                 check      = (char)((m->items[j].flags & DEMOWIN_ITM_CHK_STATE) ? 'X' : ' ');
1670                 para_start = (char)((m->items[j].flags & DEMOWIN_ITM_DISABLED)  ? '(' : ' ');
1671                 para_end   = (char)((m->items[j].flags & DEMOWIN_ITM_DISABLED)  ? ')' : ' ');
1672                 link       = (char)((NULL != m->items[j].link)                  ? '>' : ' ');
1673 
1674                 DEMOWinPrintfXY(w, 0, (u16)i, "%c %c%s%c %c", check, para_start, m->items[(u16)j].name, para_end, link);
1675             }
1676             j++;
1677         }
1678 
1679 
1680 } // End __DEMOWinMenu_display_menu()
1681 
1682 
1683 /*---------------------------------------------------------------------------*
1684  * Name        : DEMOWinPadInit()
1685  *
1686  * Description : Obvious
1687  *
1688  * Arguments   : None.
1689  *
1690  * Returns     : None.
1691  *
1692  *---------------------------------------------------------------------------*/
1693 
DEMOWinPadInit(DEMOWinPadInfo * p)1694 void DEMOWinPadInit(DEMOWinPadInfo *p)
1695 {
1696     u16 i;
1697 
1698 
1699         for (i=0; i<PAD_MAX_CONTROLLERS ;i++)
1700         {
1701             p->old_button[i] = 0;
1702             p->changed_button [i] = 0;
1703             p->repeat_button  [i] = 0;
1704             p->repeat_ctr     [i] = 0;
1705         }
1706 }
1707 
1708 /*---------------------------------------------------------------------------*
1709  * Name        : DEMOWinPadRead()
1710  *
1711  * Description : Obvious
1712  *
1713  * Arguments   : None.
1714  *
1715  * Returns     : None.
1716  *
1717  *---------------------------------------------------------------------------*/
DEMOWinPadRead(DEMOWinPadInfo * p)1718 void DEMOWinPadRead(DEMOWinPadInfo *p)
1719 {
1720 
1721     PADStatus *pad;
1722 
1723     u16 index;
1724 
1725     u32 curr;
1726     u32 old;
1727 
1728     u32 repeat;
1729 
1730 
1731         PADRead(p->pads);
1732 
1733         for (index=0; index<PAD_MAX_CONTROLLERS; index++)
1734         {
1735 
1736             old  = p->old_button[index];
1737             pad  = &(p->pads[index]);
1738 
1739             curr = ( (pad->stickX       >  PAD_THRESHOLD)? DEMOWIN_STICK_R : 0 ) |
1740                    ( (pad->stickX       < -PAD_THRESHOLD)? DEMOWIN_STICK_L : 0 ) |
1741                    ( (pad->stickY       >  PAD_THRESHOLD)? DEMOWIN_STICK_U : 0 ) |
1742                    ( (pad->stickY       < -PAD_THRESHOLD)? DEMOWIN_STICK_D : 0 ) |
1743                    ( (pad->substickX    >  PAD_THRESHOLD)? DEMOWIN_SUBSTICK_R : 0 ) |
1744                    ( (pad->substickX    < -PAD_THRESHOLD)? DEMOWIN_SUBSTICK_L : 0 ) |
1745                    ( (pad->substickY    >  PAD_THRESHOLD)? DEMOWIN_SUBSTICK_U : 0 ) |
1746                    ( (pad->substickY    < -PAD_THRESHOLD)? DEMOWIN_SUBSTICK_D : 0 ) |
1747                    ( (pad->triggerLeft  >  TRIGGER_THRESHOLD)? DEMOWIN_TRIGGER_L : 0 ) |
1748                    ( (pad->triggerRight >  TRIGGER_THRESHOLD)? DEMOWIN_TRIGGER_R : 0 ) |
1749                    (u32)pad->button;
1750 
1751             p->changed_button[index] = (u32)((old ^ curr) & curr);
1752 
1753             if (curr)
1754             {
1755                 if (old == curr)
1756                 {
1757                     p->repeat_ctr[index]++;
1758                 }
1759                 else
1760                 {
1761                     p->repeat_ctr[index] = 1;
1762                 }
1763             }
1764             else
1765             {
1766                 p->repeat_ctr[index] = 0;
1767             }
1768 
1769             repeat = p->repeat_ctr[index];
1770 
1771             if (repeat == 1)
1772             {
1773                 p->repeat_button[index] = curr;
1774             }
1775             else if (repeat > __DEMOWIN_PAD_repeat_threshold)
1776             {
1777                 if ( ((repeat - __DEMOWIN_PAD_repeat_threshold) % __DEMOWIN_PAD_repeat_rate) == 0)
1778                 {
1779                     p->repeat_button[index] = curr;
1780                 }
1781                 else
1782                 {
1783                     p->repeat_button[index] = 0;
1784                 }
1785             }
1786             else
1787             {
1788                 p->repeat_button[index] = 0;
1789             }
1790             p->old_button[index] = curr;
1791         }
1792 
1793 } // End DEMOWinPadRead()
1794 
1795 /*---------------------------------------------------------------------------*
1796  * Name        : __DEMOWinMenu_get_user_input()
1797  *
1798  * Description : Obvious
1799  *
1800  * Arguments   : None.
1801  *
1802  * Returns     : None.
1803  *
1804  *---------------------------------------------------------------------------*/
1805 
__DEMOWinMenu_get_user_input(DEMOWinPadInfo * p)1806 static u16 __DEMOWinMenu_get_user_input(DEMOWinPadInfo *p)
1807 {
1808 
1809     u16 user_input;
1810 
1811         DEMOWinPadRead(p);
1812 
1813         if (p->repeat_button[0] &  (PAD_BUTTON_UP|DEMOWIN_STICK_U))
1814         {
1815             user_input = DEMOWIN_MNU_UP;
1816         }
1817         else if (p->repeat_button[0] &  (PAD_BUTTON_DOWN|DEMOWIN_STICK_D))
1818         {
1819             user_input = DEMOWIN_MNU_DOWN;
1820         }
1821         else if (p->repeat_button[0] &  (PAD_BUTTON_LEFT|DEMOWIN_STICK_L))
1822         {
1823             user_input = DEMOWIN_MNU_LEFT;
1824         }
1825         else if (p->repeat_button[0] &  (PAD_BUTTON_RIGHT|DEMOWIN_STICK_R))
1826         {
1827             user_input = DEMOWIN_MNU_RIGHT;
1828         }
1829         else if (p->changed_button[0] & PAD_BUTTON_A) // no repeat!
1830         {
1831             user_input = DEMOWIN_MNU_SELECT;
1832         }
1833         else if (p->changed_button[0] & PAD_BUTTON_B) // no repeat!
1834         {
1835             user_input = DEMOWIN_MNU_CANCEL;
1836         }
1837         else
1838         {
1839             user_input = 0;
1840         }
1841 
1842 /*
1843         if (PADButtonDown(*old_button, pads[0].button) & PAD_BUTTON_UP)
1844         {
1845             user_input = DEMOWIN_MNU_UP;
1846         }
1847         else if (PADButtonDown(*old_button, pads[0].button) & PAD_BUTTON_DOWN)
1848         {
1849             user_input = DEMOWIN_MNU_DOWN;
1850         }
1851         else if (PADButtonDown(*old_button, pads[0].button) & PAD_BUTTON_LEFT)
1852         {
1853             user_input = DEMOWIN_MNU_LEFT;
1854         }
1855         else if (PADButtonDown(*old_button, pads[0].button) & PAD_BUTTON_RIGHT)
1856         {
1857             user_input = DEMOWIN_MNU_RIGHT;
1858         }
1859         else if (PADButtonDown(*old_button, pads[0].button) & PAD_BUTTON_A)
1860         {
1861             user_input = DEMOWIN_MNU_SELECT;
1862         }
1863         else if (PADButtonDown(*old_button, pads[0].button) & PAD_BUTTON_B)
1864         {
1865             user_input = DEMOWIN_MNU_CANCEL;
1866         }
1867         else
1868         {
1869             user_input = 0;
1870         }
1871 
1872         *old_button = pads[0].button;
1873 */
1874 
1875         return(user_input);
1876 
1877 } // End __DEMOWinMenu_display_menu()
1878 
1879 
1880 /*---------------------------------------------------------------------------*
1881  * Name        : DEMOWinSetRepeat()
1882  *
1883  * Description : Obvious
1884  *
1885  * Arguments   : None.
1886  *
1887  * Returns     : None.
1888  *
1889  *---------------------------------------------------------------------------*/
DEMOWinSetRepeat(u32 threshold,u32 rate)1890 void DEMOWinSetRepeat(u32 threshold, u32 rate)
1891 {
1892 
1893     __DEMOWIN_PAD_repeat_rate = rate;
1894     __DEMOWIN_PAD_repeat_threshold = threshold;
1895 
1896 } // End DEMOWinSetRepeat()
1897 
1898 /*---------------------------------------------------------------------------*
1899  * Name        : DEMOWinResetRepeat()
1900  *
1901  * Description : Obvious
1902  *
1903  * Arguments   : None.
1904  *
1905  * Returns     : None.
1906  *
1907  *---------------------------------------------------------------------------*/
1908 
DEMOWinResetRepeat(void)1909 void DEMOWinResetRepeat(void)
1910 {
1911 
1912     __DEMOWIN_PAD_repeat_threshold = DEMOWIN_PAD_REPEAT_THRESH_DEF;
1913     __DEMOWIN_PAD_repeat_rate      = DEMOWIN_PAD_REPEAT_RATE_DEF;
1914 
1915 } // End DEMOWinResetRepeat()
1916 
1917 
1918 /*---------------------------------------------------------------------------*
1919  * Name        : DEMOWinCreateListWindow()
1920  *
1921  * Description : Obvious
1922  *
1923  * Arguments   : None.
1924  *
1925  * Returns     : None.
1926  *
1927  *---------------------------------------------------------------------------*/
1928 
DEMOWinCreateListWindow(DEMOWinListInfo * list,u16 x,u16 y)1929 DEMOWinListInfo *DEMOWinCreateListWindow(DEMOWinListInfo *list, u16 x, u16 y)
1930 {
1931 
1932     DEMOWinListItem *ptr;
1933 
1934 
1935         ASSERTMSG(list, "DEMOWinCreateListWindow(): List is NULL!\n");
1936 
1937         // Calculate max name/title string length
1938         // Calculate number of items in list
1939         ptr = list->items;
1940 
1941         list->max_str_len = strlen(list->title);
1942         list->num_items   = 0;
1943 
1944         while (!(ptr->flags & DEMOWIN_ITM_TERMINATOR))
1945         {
1946             if (strlen(ptr->name) > list->max_str_len)
1947             {
1948                 list->max_str_len = strlen(ptr->name);
1949             }
1950             (list->num_items)++;
1951             ptr++;
1952         }
1953 
1954         // Calculate actual number of items to display
1955         // It may be less than the max number specified by the user
1956         if (list->num_items > list->max_display_items)
1957         {
1958             list->num_display_items = list->max_display_items;
1959         }
1960         else
1961         {
1962             list->num_display_items = list->num_items;
1963         }
1964 
1965         // Open window.
1966         // Note: this call will ASSERT if it fails to allocate a window
1967         list->handle = DEMOWinCreateWindow((s16)x,
1968                                            (s16)y,
1969                                            (s16)(x + DEMOWIN_CALC_MENU_WIDTH_PIXELS(list->max_str_len)),
1970                                            (s16)(y + DEMOWIN_CALC_MENU_HEIGHT_PIXELS(list->num_display_items)),
1971                                             list->title,
1972                                             0,                              // No scrollback lines! Menu function handles list scrolling
1973                                             __DEMOWinList_refresh_list);    // No callback function
1974 
1975 
1976         // Set parent of this window to this list
1977         (list->handle)->parent = (void *)(list);
1978 
1979 
1980         if (list->num_items)
1981         {
1982             return(list);
1983         }
1984 
1985         return(NULL);
1986 
1987 
1988 } // End DEMOWinCreateListWindow()
1989 
1990 /*---------------------------------------------------------------------------*
1991  * Name        : DEMOWinDestroyListWindow()
1992  *
1993  * Description : Obvious
1994  *
1995  * Arguments   : None.
1996  *
1997  * Returns     : None.
1998  *
1999  *---------------------------------------------------------------------------*/
2000 
DEMOWinDestroyListWindow(DEMOWinListInfo * list)2001 void DEMOWinDestroyListWindow(DEMOWinListInfo *list)
2002 {
2003 
2004     if (list->handle)
2005     {
2006         DEMOWinCloseWindow(list->handle);
2007         DEMOWinDestroyWindow(list->handle);
2008 
2009         list->handle = NULL;
2010     }
2011 
2012 } // End DEMOWinDestroyListWindow()
2013 
2014 
2015 /*---------------------------------------------------------------------------*
2016  * Name        : __DEMOWinList_update_list()
2017  *
2018  * Description : Obvious
2019  *
2020  * Arguments   : None.
2021  *
2022  * Returns     : None.
2023  *
2024  *---------------------------------------------------------------------------*/
2025 
__DEMOWinList_refresh_list(DEMOWinInfo * w)2026 static void __DEMOWinList_refresh_list(DEMOWinInfo *w)
2027 {
2028 
2029 
2030     DEMOWinListInfo *l;
2031 
2032     s32  i;
2033     s32  j;
2034 
2035         // The parent better the hell be a List info structure
2036         l = (w->parent);
2037 
2038         // Just in case...
2039         l->curr_pos = l->curr_pos % l->num_items;
2040 
2041         // Fix display pointer
2042         if (l->curr_pos > (l->display_pos+l->num_display_items-1))
2043         {
2044             l->display_pos = l->curr_pos - l->num_display_items + 1;
2045 
2046         }
2047         else if (l->curr_pos < l->display_pos)
2048         {
2049             l->display_pos = l->curr_pos;
2050         }
2051 
2052         if (l->cursor_state)
2053         {
2054             // Calculate cursor line
2055             if (l->display_pos > l->curr_pos)
2056             {
2057                 w->cursor_line = (s16)(l->display_pos - l->curr_pos);
2058             }
2059             else
2060             {
2061                 w->cursor_line = (s16)(l->curr_pos - l->display_pos);
2062             }
2063 
2064         }// End cursor state check
2065         else
2066         {
2067             w->cursor_line = -1;
2068         }
2069 
2070         // Display menu
2071         DEMOWinClearWindow(w);
2072 
2073 
2074         j = l->display_pos;
2075 
2076         for (i=0; i<l->num_display_items; i++)
2077         {
2078             if (!(l->items[j].flags & DEMOWIN_ITM_SEPARATOR))
2079             {
2080                 DEMOWinPrintfXY(w, 0, (u16)i, " %s ",l->items[(u16)j].name);
2081             }
2082             j++;
2083         }
2084 
2085 
2086 } // End __DEMOWinList_update_list()
2087 
2088 /*---------------------------------------------------------------------------*
2089  * Name        : DEMOWinListSetCursor()
2090  *
2091  * Description : Obvious
2092  *
2093  * Arguments   : TRUE or FALSE.
2094  *
2095  * Returns     : None.
2096  *
2097  *---------------------------------------------------------------------------*/
2098 
DEMOWinListSetCursor(DEMOWinListInfo * list,BOOL x)2099 void DEMOWinListSetCursor(DEMOWinListInfo *list, BOOL x)
2100 {
2101 
2102     list->cursor_state = x;
2103 
2104 } // End DEMOWinListSetCursor()
2105 
2106 
2107 /*---------------------------------------------------------------------------*
2108  * Name        : DEMOWinListScrollList()
2109  *
2110  * Description : Obvious
2111  *
2112  * Arguments   : TRUE or FALSE.
2113  *
2114  * Returns     : None.
2115  *
2116  *---------------------------------------------------------------------------*/
2117 
DEMOWinListScrollList(DEMOWinListInfo * list,u32 dir)2118 s32 DEMOWinListScrollList(DEMOWinListInfo *list, u32 dir)
2119 {
2120 
2121     ASSERTMSG(list, "DEMOWinListScrollList(): NULL handle!\n");
2122 
2123     switch(dir)
2124     {
2125         case DEMOWIN_SCROLL_UP:
2126             if (list->display_pos)
2127             {
2128                 // If it's zero, don't allow scroll
2129                 list->display_pos = (u16)((list->display_pos - 1 + list->num_items) % (list->num_items));
2130             }
2131             break;
2132 
2133         case DEMOWIN_SCROLL_DOWN:
2134             if (list->display_pos < (list->num_items - list->num_display_items))
2135             {
2136                 // If display_pos is at the start of the last 'pageful' of items, then don't allow scroll
2137                 list->display_pos = (u16)((list->display_pos + 1) % (list->num_items));
2138             }
2139             break;
2140 
2141         case DEMOWIN_SCROLL_HOME:
2142             list->display_pos = 0;
2143             break;
2144 
2145         default:
2146             ASSERTMSG(0, "DEMOWinListScrollList(): Invalid dimension!\n");
2147             break;
2148     }
2149 
2150     // Fix up current_pos
2151 
2152     if (list->curr_pos > (list->display_pos+list->num_display_items-1))
2153     {
2154         list->curr_pos = list->display_pos + list->num_display_items - 1;
2155     }
2156     else if (list->curr_pos < list->display_pos)
2157     {
2158         list->curr_pos = list->display_pos;
2159     }
2160 
2161 
2162     return(list->display_pos);
2163 
2164 } // End DEMOWinListScrollList()
2165 
2166 
2167 /*---------------------------------------------------------------------------*
2168  * Name        : DEMOWinListSetCursor()
2169  *
2170  * Description : Obvious
2171  *
2172  * Arguments   : TRUE or FALSE.
2173  *
2174  * Returns     : None.
2175  *
2176  *---------------------------------------------------------------------------*/
2177 
DEMOWinListMoveCursor(DEMOWinListInfo * list,u32 dir)2178 s32 DEMOWinListMoveCursor(DEMOWinListInfo *list, u32 dir)
2179 {
2180 
2181     ASSERTMSG(list, "DEMOWinListScrollList(): NULL handle!\n");
2182 
2183     switch(dir)
2184     {
2185         case DEMOWIN_LIST_UP:
2186             list->curr_pos = (list->curr_pos + list->num_items - 1) % list->num_items;
2187             break;
2188 
2189         case DEMOWIN_LIST_DOWN:
2190             list->curr_pos = (list->curr_pos + 1) % list->num_items;
2191             break;
2192 
2193         default:
2194             ASSERTMSG(0, "DEMOWinListMoveCursor(): Invalid dimension!\n");
2195             break;
2196     }
2197 
2198 
2199     return(list->curr_pos);
2200 
2201 } // End DEMOWinListMoveCursor()
2202 
2203