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