/*============================================================================= Name : UIcontrols.c Purpose : Functions for basic UI control types (buttons etc.) Created 7/7/1997 by lmoloney Copyright Relic Entertainment, Inc. All rights reserved. =============================================================================*/ #ifndef SW_Render #include #endif #include "glinc.h" #include "types.h" #include "region.h" #include "color.h" #include "prim2d.h" #include "mouse.h" #include "font.h" #include "fontreg.h" #include "soundevent.h" #include "uicontrols.h" #include "scroller.h" #include "scenpick.h" #include "FeReg.h" #include "mainswitches.h" #include "mouse.h" #include "universe.h" #include "utility.h" #include "task.h" #include "strings.h" #include "glcaps.h" // Keyboard navigation callback functions #define ATOM_FLAG 0 #define REGION_FLAG 1 /*============================================================================= Data: =============================================================================*/ color FEC_ListItemTranslucent; color FEC_ListItemTranslucentBorder; color FEC_ListItemStandard; color FEC_ListItemSelected; color FEC_ListItemInactive; color FEC_ListItemInvalid; color FEC_Background; color TB_SelectedColor = colRGB(255,255,255); color TB_HyperspaceColor = colRGB(32,220,32); color TB_CompleteColor = colRGB(0,160,200); color TB_IncompleteColor = colRGB(25,90,90); scriptEntry FrontEndColourTweaks[] = { makeEntry(FEC_ListItemTranslucent, scriptSetRGBACB), makeEntry(FEC_ListItemTranslucentBorder, scriptSetRGBCB), makeEntry(FEC_ListItemStandard, scriptSetRGBCB), makeEntry(FEC_ListItemSelected, scriptSetRGBCB), makeEntry(FEC_ListItemInactive, scriptSetRGBCB), makeEntry(FEC_ListItemInvalid, scriptSetRGBCB), makeEntry(FEC_Background, scriptSetRGBCB), makeEntry(TB_SelectedColor, scriptSetRGBCB), makeEntry(TB_HyperspaceColor, scriptSetRGBCB), makeEntry(TB_CompleteColor, scriptSetRGBCB), makeEntry(TB_IncompleteColor, scriptSetRGBCB), endEntry }; void uicButtonDraw(regionhandle reg); udword uicButtonProcess(regionhandle region, sdword ID, udword event, udword data); void uicToggleDraw(regionhandle reg); udword uicToggleProcess(regionhandle region, sdword ID, udword event, udword data); void uicCheckBoxDraw(regionhandle reg); udword uicRadioButtonProcess(regionhandle region, sdword ID, udword event, udword data); void uicRadioButtonDraw(regionhandle reg); udword uicScrollBarProcess(regionhandle region, sdword ID, udword event, udword data); void uicScrollBarDraw(regionhandle reg); void uicScrollBarButtonDraw(regionhandle reg); udword uicListWindowProcess(regionhandle region, sdword ID, udword event, udword data); void uicListWindowDraw(regionhandle reg); udword uicTextEntryProcess(regionhandle reg, sdword ID, udword event, udword data); void uicTextEntryDraw(regionhandle reg); //udword uicBitmapButtonProcess(regionhandle reg, sdword ID, udword event, udword data); void uicBitmapButtonDraw(regionhandle reg); udword uicHorizSliderProcess(regionhandle region, sdword ID, udword event, udword data); udword uicVertSliderProcess(regionhandle region, sdword ID, udword event, udword data); void uicHorizSliderDraw(regionhandle reg); void uicVertSliderDraw(regionhandle reg); udword uicDragButtonProcess(regionhandle region, sdword ID, udword event, udword data); bool uicClearCurrent(regionhandle reg); void uicSetCurrent(regionhandle reg, bool bUserInput); void uicLimitTabstop(sdword num_buttons); //global variables to pass drag information sdword uicDragX = 0; sdword uicDragY = 0; //table of process/draw functions and region filters for a variety of control types struct { regionfunction function; regiondrawfunction drawFunction; udword regionFilter; } uicControlFunctions[] = { {NULL, NULL, 0}, //Nothing {NULL, NULL, 0}, //FA_UserRegion = 1, {NULL, NULL, 0}, //FA_StaticText, {uicButtonProcess, uicButtonDraw, UIF_Button}, //FA_Button, {uicToggleProcess, uicCheckBoxDraw, UIF_Button}, //FA_CheckBox, {uicToggleProcess, uicToggleDraw, UIF_Button}, //FA_ToggleButton, {NULL, NULL, 0}, //FA_HorizScrollBar, {NULL, NULL, 0}, //FA_VerticalScrollBar, {NULL, NULL, 0}, //FA_TextEntry, {NULL, NULL, 0}, //FA_ListViewExpandButton, {NULL, NULL, 0}, //FA_TitleBar, {NULL, NULL, 0}, //FA_MenuItem, {uicRadioButtonProcess, uicRadioButtonDraw, UIF_Button}, //FA_RadioButton, {NULL, NULL, 0}, //FA_CutoutRegion, {NULL, NULL, 0}, //FA_DecorativeRegion, {NULL, NULL, 0}, //FA_Divider, {NULL, NULL, 0}, //FA_ListWindow, {uicToggleProcess, uicBitmapButtonDraw,UIF_Button}, //FA_BitmapButton, {uicHorizSliderProcess, uicHorizSliderDraw, UIF_Button}, //FA_HorizSlider, {uicVertSliderProcess, uicVertSliderDraw, UIF_Button}, //FA_VertSlider, {uicDragButtonProcess, uicButtonDraw, UIF_DragButton} //FA_DragButton, }; //space characters to delineate words for CTRL-cursor movement char uicSpaceCharacters[] = " \\/()`'\".,"; typedef struct uicKeyTable { char regularKey; char shiftKey; } uicKeyTable; uicKeyTable uicKeyEntryTable[KEY_TOTAL_KEYS] = { /* 0 0 */ 0, 0, /* 1 */ 0, 0, /* 2 */ 0, 0, /* 3 */ 0, 0, /* 4 */ 0, 0, /* 5 */ 0, 0, /* 6 */ 0, 0, /* 7 */ 0, 0, /* 8 */ 0, 0, /* 9 */ 0, 0, /* 10 */ 0, 0, /* 11 */ 0, 0, /* 12 */ 0, 0, /* 13 */ 0, 0, /* 14 */ 0, 0, /* 15 */ 0, 0, /* 16 16 */ 0, 0, /* 17 */ 0, 0, /* 18 */ 0, 0, /* 19 */ 0, 0, /* 20 */ 0, 0, /* 21 */ 0, 0, /* 22 */ 0, 0, /* 23 */ 0, 0, /* 24 */ 0, 0, /* 25 */ 0, 0, /* 26 */ 0, 0, /* 27 */ 0, 0, /* 28 */ 0, 0, /* 29 */ 0, 0, /* 30 */ 0, 0, /* 31 */ 0, 0, /* space 32 32 */ ' ', ' ', /* 33 */ 0, 0, /* 34 */ 0, 0, /* 35 */ 0, 0, /* 36 */ 0, 0, /* 37 */ 0, 0, /* 38 */ 0, 0, /* punctuation 39 */ 0, 0, /* 40 */ 0, 0, /* 41 */ 0, 0, /* 42 */ 0, 0, /* 43 */ 0, 0, /* 44 */ 0, 0, /* 45 */ '-', '_', /* 46 */ 0, 0, /* 47 */ 0, 0, /* 0 48 48 */ '0', ')', /* 1 49 */ '1', '!', /* 2 50 */ '2', '@', /* 3 51 */ '3', '#', /* 4 52 */ '4', '$', /* 5 53 */ '5', '%', /* 6 54 */ '6', '^', /* 7 55 */ '7', '&', /* 8 56 */ '8', '*', /* 9 57 */ '9', '(', /* : 58 */ ':', 0, /* ; 59 */ ';', 0, /* < 60 */ '<', 0, /* = 61 */ '=', '+', /* > 62 */ '>', 0, /* ? 63 */ '?', 0, /* @ 64 64 */ '@', 0, /* A 65 */ 'a', 'A', /* B 66 */ 'b', 'B', /* C 67 */ 'c', 'C', /* D 68 */ 'd', 'D', /* E 69 */ 'e', 'E', /* F 70 */ 'f', 'F', /* G 71 */ 'g', 'G', /* H 72 */ 'h', 'H', /* I 73 */ 'i', 'I', /* J 74 */ 'j', 'J', /* K 75 */ 'k', 'K', /* L 76 */ 'l', 'L', /* M 77 */ 'm', 'M', /* N 78 */ 'n', 'N', /* O 79 */ 'o', 'O', /* P 80 80 */ 'p', 'P', /* Q 81 */ 'q', 'Q', /* R 82 */ 'r', 'R', /* S 83 */ 's', 'S', /* T 84 */ 't', 'T', /* U 85 */ 'u', 'U', /* V 86 */ 'v', 'V', /* W 87 */ 'w', 'W', /* X 88 */ 'x', 'X', /* Y 89 */ 'y', 'Y', /* Z 90 */ 'z', 'Z', /* 91 */ 0, 0, /* 92 */ 0, 0, /* 93 */ 0, 0, /* 94 */ 0, 0, /* 95 */ 0, 0, /* 96 96 */ '0', 0, /* 97 */ '1', 0, /* 98 */ '2', 0, /* 99 */ '3', 0, /* 100*/ '4', 0, /* 101*/ '5', 0, /* 102*/ '6', 0, /* 103*/ '7', 0, /* 104*/ '8', 0, /* 105*/ '9', 0, /* 106*/ '*', 0, /* 107*/ '+', 0, /* 108*/ 0, 0, /* 109*/ '-', 0, /* 110*/ '.', 0, /* 111*/ '/', 0, /* 112 112*/ 0, 0, /* 113*/ 0, 0, /* 114*/ 0, 0, /* 115*/ 0, 0, /* 116*/ 0, 0, /* 117*/ 0, 0, /* 118*/ 0, 0, /* 119*/ 0, 0, /* 120*/ 0, 0, /* 121*/ 0, 0, /* 122*/ 0, 0, /* 123*/ 0, 0, /* 124*/ 0, 0, /* 125*/ 0, 0, /* 126*/ 0, 0, /* 127*/ 0, 0, /* 128 128*/ 0, 0, /* 129*/ 0, 0, /* 130*/ 0, 0, /* 131*/ 0, 0, /* 132*/ 0, 0, /* 133*/ 0, 0, /* 134*/ 0, 0, /* 135*/ 0, 0, /* 136*/ 0, 0, /* 137*/ 0, 0, /* 138*/ 0, 0, /* 139*/ 0, 0, /* 140*/ 0, 0, /* 141*/ 0, 0, /* 142*/ 0, 0, /* 143*/ 0, 0, /* 144 144*/ 0, 0, /* 145*/ 0, 0, /* 146*/ 0, 0, /* 147*/ 0, 0, /* 148*/ 0, 0, /* 149*/ 0, 0, /* 150*/ 0, 0, /* 151*/ 0, 0, /* 152*/ 0, 0, /* 153*/ 0, 0, /* 154*/ 0, 0, /* 155*/ 0, 0, /* 156*/ 0, 0, /* 157*/ 0, 0, /* 158*/ 0, 0, /* 159*/ 0, 0, /* 160 160*/ 0, 0, /* 161*/ 0, 0, /* 162*/ 0, 0, /* 163*/ 0, 0, /* 164*/ 0, 0, /* 165*/ 0, 0, /* 166*/ 0, 0, /* 167*/ 0, 0, /* 168*/ 0, 0, /* 169*/ 0, 0, /* 170*/ 0, 0, /* 171*/ 0, 0, /* 172*/ 0, 0, /* 173*/ 0, 0, /* 174*/ 0, 0, /* 175*/ 0, 0, /* 176 176*/ 0, 0, /* 177*/ 0, 0, /* 178*/ 0, 0, /* 179*/ 0, 0, /* 180*/ 0, 0, /* 181*/ 0, 0, /* 182*/ 0, 0, /* 183*/ 0, 0, /* 184*/ 0, 0, /* 185*/ 0, 0, /* 186*/ ';', ':', /* 187*/ '=', '+', /* 188*/ ',', '<', /* 189*/ '-', '_', /* 190*/ '.', '>', /* 191*/ '/', '?', /* 192 192*/ '`', '~', /* 193*/ 0, 0, /* 194*/ 0, 0, /* 195*/ 0, 0, /* 196*/ 0, 0, /* 197*/ 0, 0, /* 198*/ 0, 0, /* 199*/ 0, 0, /* 200*/ 0, 0, /* 201*/ 0, 0, /* 202*/ 0, 0, /* 203*/ 0, 0, /* 204*/ 0, 0, /* 205*/ 0, 0, /* 206*/ 0, 0, /* 207*/ 0, 0, /* 208 208*/ 0, 0, /* 209*/ 0, 0, /* 210*/ 0, 0, /* 211*/ 0, 0, /* 212*/ 0, 0, /* 213*/ 0, 0, /* 214*/ 0, 0, /* 215*/ 0, 0, /* 216*/ 0, 0, /* 217*/ 0, 0, /* 218*/ 0, 0, /* 219*/ '[', '{', /* 220*/ '\\', '|', /* 221*/ ']', '}', /* 222*/ '\'', '"', /* 223*/ 0, 0, /* 224 224*/ 0, 0, /* 225*/ 0, 0, /* 226*/ 0, 0, /* 227*/ 0, 0, /* 228*/ 0, 0, /* 229*/ 0, 0, /* 230*/ 0, 0, /* 231*/ 0, 0, /* 232*/ 0, 0, /* 233*/ 0, 0, /* 234*/ 0, 0, /* 235*/ 0, 0, /* 236*/ 0, 0, /* 237*/ 0, 0, /* 238*/ 0, 0, /* 239*/ 0, 0, /* 240 240*/ 0, 0, /* 241*/ 0, 0, /* 242*/ 0, 0, /* 243*/ 0, 0, /* 244*/ 0, 0, /* 245*/ 0, 0, /* 246*/ 0, 0, /* 247*/ 0, 0, /* 248*/ 0, 0, /* 249*/ 0, 0, /* 250*/ 0, 0, /* 251*/ 0, 0, /* 252*/ 0, 0, /* 253*/ 0, 0, /* 254*/ 0, 0, /* 255*/ 0, 0, }; uicKeyTable uicFrenchKeyEntryTable[KEY_TOTAL_KEYS] = { /* 0 0 */ 0, 0, /* 1 */ 0, 0, /* 2 */ 0, 0, /* 3 */ 0, 0, /* 4 */ 0, 0, /* 5 */ 0, 0, /* 6 */ 0, 0, /* 7 */ 0, 0, /* 8 */ 0, 0, /* 9 */ 0, 0, /* 10 */ 0, 0, /* 11 */ 0, 0, /* 12 */ 0, 0, /* 13 */ 0, 0, /* 14 */ 0, 0, /* 15 */ 0, 0, /* 16 16 */ 0, 0, /* 17 */ 0, 0, /* 18 */ 0, 0, /* 19 */ 0, 0, /* 20 */ 0, 0, /* 21 */ 0, 0, /* 22 */ 0, 0, /* 23 */ 0, 0, /* 24 */ 0, 0, /* 25 */ 0, 0, /* 26 */ 0, 0, /* 27 */ 0, 0, /* 28 */ 0, 0, /* 29 */ 0, 0, /* 30 */ 0, 0, /* 31 */ 0, 0, /* space 32 32 */ ' ', ' ', /* 33 */ 0, 0, /* 34 */ 0, 0, /* 35 */ 0, 0, /* 36 */ 0, 0, /* 37 */ 0, 0, /* 38 */ 0, 0, /* punctuation 39 */ 0, 0, /* 40 */ 0, 0, /* 41 */ 0, 0, /* 42 */ 0, 0, /* 43 */ 0, 0, /* 44 */ ',', '?', /* 45 */ '-', '_', /* 46 */ 0, 0, /* 47 */ 0, 0, /* 0 48 48 */ 'à', '0', /* 1 49 */ '&', '1', /* 2 50 */ 'é', '2', /* 3 51 */ '"', '3', /* 4 52 */ '\'', '4', /* 5 53 */ '(', '5', /* 6 54 */ '-', '6', /* 7 55 */ 'è', '7', /* 8 56 */ '_', '8', /* 9 57 */ 'ç', '9', /* : 58 */ ':', 0, /* ; 59 */ ';', 0, /* < 60 */ '<', 0, /* = 61 */ '=', '+', /* > 62 */ '>', 0, /* ? 63 */ '?', 0, /* @ 64 64 */ '@', 0, /* A 65 */ 'a', 'A', /* B 66 */ 'b', 'B', /* C 67 */ 'c', 'C', /* D 68 */ 'd', 'D', /* E 69 */ 'e', 'E', /* F 70 */ 'f', 'F', /* G 71 */ 'g', 'G', /* H 72 */ 'h', 'H', /* I 73 */ 'i', 'I', /* J 74 */ 'j', 'J', /* K 75 */ 'k', 'K', /* L 76 */ 'l', 'L', /* M 77 */ 'm', 'M', /* N 78 */ 'n', 'N', /* O 79 */ 'o', 'O', /* P 80 80 */ 'p', 'P', /* Q 81 */ 'q', 'Q', /* R 82 */ 'r', 'R', /* S 83 */ 's', 'S', /* T 84 */ 't', 'T', /* U 85 */ 'u', 'U', /* V 86 */ 'v', 'V', /* W 87 */ 'w', 'W', /* X 88 */ 'x', 'X', /* Y 89 */ 'y', 'Y', /* Z 90 */ 'z', 'Z', /* 91 */ 0, 0, /* 92 */ 0, 0, /* 93 */ 0, 0, /* 94 */ 0, 0, /* 95 */ 0, 0, /* 96 96 */ '0', 0, /* 97 */ '1', 0, /* 98 */ '2', 0, /* 99 */ '3', 0, /* 100*/ '4', 0, /* 101*/ '5', 0, /* 102*/ '6', 0, /* 103*/ '7', 0, /* 104*/ '8', 0, /* 105*/ '9', 0, /* 106*/ '*', 0, /* 107*/ '+', 0, /* 108*/ 0, 0, /* 109*/ '-', 0, /* 110*/ '.', 0, /* 111*/ '/', 0, /* 112 112*/ 0, 0, /* 113*/ 0, 0, /* 114*/ 0, 0, /* 115*/ 0, 0, /* 116*/ 0, 0, /* 117*/ 0, 0, /* 118*/ 0, 0, /* 119*/ 0, 0, /* 120*/ 0, 0, /* 121*/ 0, 0, /* 122*/ 0, 0, /* 123*/ 0, 0, /* 124*/ 0, 0, /* 125*/ 0, 0, /* 126*/ 0, 0, /* 127*/ 0, 0, /* 128 128*/ 0, 0, /* 129*/ 0, 0, /* 130*/ 0, 0, /* 131*/ 0, 0, /* 132*/ 0, 0, /* 133*/ 0, 0, /* 134*/ 0, 0, /* 135*/ 0, 0, /* 136*/ 0, 0, /* 137*/ 0, 0, /* 138*/ 0, 0, /* 139*/ 0, 0, /* 140*/ 0, 0, /* 141*/ 0, 0, /* 142*/ 0, 0, /* 143*/ 0, 0, /* 144 144*/ 0, 0, /* 145*/ 0, 0, /* 146*/ 0, 0, /* 147*/ 0, 0, /* 148*/ 0, 0, /* 149*/ 0, 0, /* 150*/ 0, 0, /* 151*/ 0, 0, /* 152*/ 0, 0, /* 153*/ 0, 0, /* 154*/ 0, 0, /* 155*/ 0, 0, /* 156*/ 0, 0, /* 157*/ 0, 0, /* 158*/ 0, 0, /* 159*/ 0, 0, /* 160 160*/ 0, 0, /* 161*/ 0, 0, /* 162*/ 0, 0, /* 163*/ 0, 0, /* 164*/ 0, 0, /* 165*/ 0, 0, /* 166*/ 0, 0, /* 167*/ '!', '§', /* 168*/ 0, 0, /* 169*/ 0, 0, /* 170*/ 0, 0, /* 171*/ 0, 0, /* 172*/ 0, 0, /* 173*/ 0, 0, /* 174*/ 0, 0, /* 175*/ 0, 0, /* 176 176*/ 0, 0, /* 177*/ 0, 0, /* 178*/ 0, 0, /* 179*/ 0, 0, /* 180*/ 0, 0, /* 181*/ 0, 0, /* 182*/ 0, 0, /* 183*/ 0, 0, /* 184*/ 0, 0, /* 185*/ 0, 0, /* 186*/ ';', ':', /* 187*/ '=', '+', /* 188*/ ';', '.', /* 189*/ ')', '°', /* 190*/ ':', '/', /* 191*/ '/', '?', /* 192 192*/ '²', 0, /* 193*/ 0, 0, /* 194*/ 0, 0, /* 195*/ 0, 0, /* 196*/ 0, 0, /* 197*/ 0, 0, /* 198*/ 0, 0, /* 199*/ 0, 0, /* 200*/ 0, 0, /* 201*/ 0, 0, /* 202*/ 0, 0, /* 203*/ 0, 0, /* 204*/ 0, 0, /* 205*/ 0, 0, /* 206*/ 0, 0, /* 207*/ 0, 0, /* 208 208*/ 0, 0, /* 209*/ 0, 0, /* 210*/ 0, 0, /* 211*/ 0, 0, /* 212*/ 0, 0, /* 213*/ 0, 0, /* 214*/ 0, 0, /* 215*/ 0, 0, /* 216*/ 0, 0, /* 217*/ 0, 0, /* 218*/ 0, 0, /* 219*/ 'ˆ', '¨', /* 220*/ '*', 'µ', /* 221*/ '$', '£', /* 222*/ '\'', '"', /* 223*/ 0, 0, /* 224 224*/ 0, 0, /* 225*/ 0, 0, /* 226*/ 0, 0, /* 227*/ 0, 0, /* 228*/ 0, 0, /* 229*/ 0, 0, /* 230*/ 0, 0, /* 231*/ 0, 0, /* 232*/ 0, 0, /* 233*/ 0, 0, /* 234*/ 0, 0, /* 235*/ 0, 0, /* 236*/ 0, 0, /* 237*/ 0, 0, /* 238*/ 0, 0, /* 239*/ 0, 0, /* 240 240*/ 0, 0, /* 241*/ 0, 0, /* 242*/ 0, 0, /* 243*/ 0, 0, /* 244*/ 0, 0, /* 245*/ 0, 0, /* 246*/ 0, 0, /* 247*/ 0, 0, /* 248*/ 0, 0, /* 249*/ 'ù', '%', /* 250*/ 0, 0, /* 251*/ 0, 0, /* 252*/ 0, 0, /* 253*/ 0, 0, /* 254*/ 0, 0, /* 255*/ 0, 0, }; uicKeyTable uicGermanKeyEntryTable[KEY_TOTAL_KEYS] = { /* 0 0 */ 0, 0, /* 1 */ 0, 0, /* 2 */ 0, 0, /* 3 */ 0, 0, /* 4 */ 0, 0, /* 5 */ 0, 0, /* 6 */ 0, 0, /* 7 */ 0, 0, /* 8 */ 0, 0, /* 9 */ 0, 0, /* 10 */ 0, 0, /* 11 */ 0, 0, /* 12 */ 0, 0, /* 13 */ 0, 0, /* 14 */ 0, 0, /* 15 */ 0, 0, /* 16 16 */ 0, 0, /* 17 */ 0, 0, /* 18 */ 0, 0, /* 19 */ 0, 0, /* 20 */ 0, 0, /* 21 */ 0, 0, /* 22 */ 0, 0, /* 23 */ 0, 0, /* 24 */ 0, 0, /* 25 */ 0, 0, /* 26 */ 0, 0, /* 27 */ 0, 0, /* 28 */ 0, 0, /* 29 */ 0, 0, /* 30 */ 0, 0, /* 31 */ 0, 0, /* space 32 32 */ ' ', ' ', /* 33 */ 0, 0, /* 34 */ 0, 0, /* 35 */ 0, 0, /* 36 */ 0, 0, /* 37 */ 0, 0, /* 38 */ 0, 0, /* punctuation 39 */ 0, 0, /* 40 */ 0, 0, /* 41 */ 0, 0, /* 42 */ 0, 0, /* 43 */ 0, 0, /* 44 */ ',', '?', /* 45 */ 0, 0, /* 46 */ 0, 0, /* 47 */ 0, 0, /* 0 48 48 */ '0', '=', /* 1 49 */ '1', '!', /* 2 50 */ '2', '"', /* 3 51 */ '3', '§', /* 4 52 */ '4', '$', /* 5 53 */ '5', '%', /* 6 54 */ '6', '&', /* 7 55 */ '7', '/', /* 8 56 */ '8', '(', /* 9 57 */ '9', ')', /* : 58 */ ':', 0, /* ; 59 */ ';', 0, /* < 60 */ '<', 0, /* = 61 */ '=', 0, /* > 62 */ '>', 0, /* ? 63 */ '?', 0, /* @ 64 64 */ '@', 0, /* A 65 */ 'a', 'A', /* B 66 */ 'b', 'B', /* C 67 */ 'c', 'C', /* D 68 */ 'd', 'D', /* E 69 */ 'e', 'E', /* F 70 */ 'f', 'F', /* G 71 */ 'g', 'G', /* H 72 */ 'h', 'H', /* I 73 */ 'i', 'I', /* J 74 */ 'j', 'J', /* K 75 */ 'k', 'K', /* L 76 */ 'l', 'L', /* M 77 */ 'm', 'M', /* N 78 */ 'n', 'N', /* O 79 */ 'o', 'O', /* P 80 80 */ 'p', 'P', /* Q 81 */ 'q', 'Q', /* R 82 */ 'r', 'R', /* S 83 */ 's', 'S', /* T 84 */ 't', 'T', /* U 85 */ 'u', 'U', /* V 86 */ 'v', 'V', /* W 87 */ 'w', 'W', /* X 88 */ 'x', 'X', /* Y 89 */ 'y', 'Y', /* Z 90 */ 'z', 'Z', /* 91 */ 0, 0, /* 92 */ 0, 0, /* 93 */ 0, 0, /* 94 */ 0, 0, /* 95 */ 0, 0, /* 96 96 */ '0', 0, /* 97 */ '1', 0, /* 98 */ '2', 0, /* 99 */ '3', 0, /* 100*/ '4', 0, /* 101*/ '5', 0, /* 102*/ '6', 0, /* 103*/ '7', 0, /* 104*/ '8', 0, /* 105*/ '9', 0, /* 106*/ '*', 0, /* 107*/ '+', 0, /* 108*/ 0, 0, /* 109*/ '-', 0, /* 110*/ '.', 0, /* 111*/ '/', 0, /* 112 112*/ 0, 0, /* 113*/ 0, 0, /* 114*/ 0, 0, /* 115*/ 0, 0, /* 116*/ 0, 0, /* 117*/ 0, 0, /* 118*/ 0, 0, /* 119*/ 0, 0, /* 120*/ 0, 0, /* 121*/ 0, 0, /* 122*/ 0, 0, /* 123*/ 0, 0, /* 124*/ 0, 0, /* 125*/ 0, 0, /* 126*/ 0, 0, /* 127*/ 0, 0, /* 128 128*/ 0, 0, /* 129*/ 0, 0, /* 130*/ 0, 0, /* 131*/ 0, 0, /* 132*/ 0, 0, /* 133*/ 0, 0, /* 134*/ 0, 0, /* 135*/ 0, 0, /* 136*/ 0, 0, /* 137*/ 0, 0, /* 138*/ 0, 0, /* 139*/ 0, 0, /* 140*/ 0, 0, /* 141*/ 0, 0, /* 142*/ 0, 0, /* 143*/ 0, 0, /* 144 144*/ 0, 0, /* 145*/ 0, 0, /* 146*/ 0, 0, /* 147*/ 0, 0, /* 148*/ 0, 0, /* 149*/ 0, 0, /* 150*/ 0, 0, /* 151*/ 0, 0, /* 152*/ 0, 0, /* 153*/ 0, 0, /* 154*/ 0, 0, /* 155*/ 0, 0, /* 156*/ 0, 0, /* 157*/ 0, 0, /* 158*/ 0, 0, /* 159*/ 0, 0, /* 160 160*/ 0, 0, /* 161*/ 0, 0, /* 162*/ 0, 0, /* 163*/ 0, 0, /* 164*/ 0, 0, /* 165*/ 0, 0, /* 166*/ 0, 0, /* 167*/ 0, 0, /* 168*/ 0, 0, /* 169*/ 0, 0, /* 170*/ 0, 0, /* 171*/ 0, 0, /* 172*/ 0, 0, /* 173*/ 0, 0, /* 174*/ 0, 0, /* 175*/ 0, 0, /* 176 176*/ 0, 0, /* 177*/ 0, 0, /* 178*/ 0, 0, /* 179*/ 0, 0, /* 180*/ 0, 0, /* 181*/ 0, 0, /* 182*/ 0, 0, /* 183*/ 0, 0, /* 184*/ 0, 0, /* 185*/ 0, 0, /* 186*/ ';', ':', /* 187*/ '´', '`', /* 188*/ ',', ';', /* 189*/ 'ß', '?', /* 190*/ '.', ':', /* 191*/ '/', '?', /* 192 192*/ 'ˆ', '°', /* 193*/ 0, 0, /* 194*/ 0, 0, /* 195*/ 0, 0, /* 196*/ 0, 0, /* 197*/ 0, 0, /* 198*/ 0, 0, /* 199*/ 0, 0, /* 200*/ '-', '_', /* 201*/ 0, 0, /* 202*/ 0, 0, /* 203*/ 0, 0, /* 204*/ 0, 0, /* 205*/ 0, 0, /* 206*/ 0, 0, /* 207*/ 0, 0, /* 208 208*/ 0, 0, /* 209*/ 0, 0, /* 210*/ 0, 0, /* 211*/ 0, 0, /* 212*/ 0, 0, /* 213*/ 0, 0, /* 214*/ 0, 0, /* 215*/ 0, 0, /* 216*/ 0, 0, /* 217*/ 0, 0, /* 218*/ 0, 0, /* 219*/ 'ü', 'Ü', /* 220*/ '#', '\'', /* 221*/ '+', '*', /* 222*/ '\'', '"', /* 223*/ 0, 0, /* 224 224*/ 0, 0, /* 225*/ 0, 0, /* 226*/ 0, 0, /* 227*/ 0, 0, /* 228*/ 'ä', 'Ä', /* 229*/ 0, 0, /* 230*/ 0, 0, /* 231*/ 0, 0, /* 232*/ 0, 0, /* 233*/ 0, 0, /* 234*/ 0, 0, /* 235*/ 0, 0, /* 236*/ 0, 0, /* 237*/ 0, 0, /* 238*/ 0, 0, /* 239*/ 0, 0, /* 240 240*/ 0, 0, /* 241*/ 0, 0, /* 242*/ 0, 0, /* 243*/ 0, 0, /* 244*/ 0, 0, /* 245*/ 0, 0, /* 246*/ 'ö', 'Ö', /* 247*/ 0, 0, /* 248*/ 0, 0, /* 249*/ 0, 0, /* 250*/ 0, 0, /* 251*/ 0, 0, /* 252*/ 0, 0, /* 253*/ 0, 0, /* 254*/ 0, 0, /* 255*/ 0, 0, }; uicKeyTable uicSpanishKeyEntryTable[KEY_TOTAL_KEYS] = { /* 0 0 */ 0, 0, /* 1 */ 0, 0, /* 2 */ 0, 0, /* 3 */ 0, 0, /* 4 */ 0, 0, /* 5 */ 0, 0, /* 6 */ 0, 0, /* 7 */ 0, 0, /* 8 */ 0, 0, /* 9 */ 0, 0, /* 10 */ 0, 0, /* 11 */ 0, 0, /* 12 */ 0, 0, /* 13 */ 0, 0, /* 14 */ 0, 0, /* 15 */ 0, 0, /* 16 16 */ 0, 0, /* 17 */ 0, 0, /* 18 */ 0, 0, /* 19 */ 0, 0, /* 20 */ 0, 0, /* 21 */ 0, 0, /* 22 */ 0, 0, /* 23 */ 0, 0, /* 24 */ 0, 0, /* 25 */ 0, 0, /* 26 */ 0, 0, /* 27 */ 0, 0, /* 28 */ 0, 0, /* 29 */ 0, 0, /* 30 */ 0, 0, /* 31 */ 0, 0, /* space 32 32 */ ' ', ' ', /* 33 */ 0, 0, /* 34 */ 0, 0, /* 35 */ 0, 0, /* 36 */ 0, 0, /* 37 */ 0, 0, /* 38 */ 0, 0, /* punctuation 39 */ 0, 0, /* 40 */ 0, 0, /* 41 */ 0, 0, /* 42 */ 0, 0, /* 43 */ 0, 0, /* 44 */ 0, 0, /* 45 */ '-', '_', /* 46 */ 0, 0, /* 47 */ 0, 0, /* 0 48 48 */ '0', '=', /* 1 49 */ '1', '!', /* 2 50 */ '2', '"', /* 3 51 */ '3', '·', /* 4 52 */ '4', '$', /* 5 53 */ '5', '%', /* 6 54 */ '6', '&', /* 7 55 */ '7', '/', /* 8 56 */ '8', '(', /* 9 57 */ '9', ')', /* : 58 */ ':', 0, /* ; 59 */ ';', 0, /* < 60 */ '<', 0, /* = 61 */ '=', '+', /* > 62 */ '>', 0, /* ? 63 */ '?', 0, /* @ 64 64 */ '@', 0, /* A 65 */ 'a', 'A', /* B 66 */ 'b', 'B', /* C 67 */ 'c', 'C', /* D 68 */ 'd', 'D', /* E 69 */ 'e', 'E', /* F 70 */ 'f', 'F', /* G 71 */ 'g', 'G', /* H 72 */ 'h', 'H', /* I 73 */ 'i', 'I', /* J 74 */ 'j', 'J', /* K 75 */ 'k', 'K', /* L 76 */ 'l', 'L', /* M 77 */ 'm', 'M', /* N 78 */ 'n', 'N', /* O 79 */ 'o', 'O', /* P 80 80 */ 'p', 'P', /* Q 81 */ 'q', 'Q', /* R 82 */ 'r', 'R', /* S 83 */ 's', 'S', /* T 84 */ 't', 'T', /* U 85 */ 'u', 'U', /* V 86 */ 'v', 'V', /* W 87 */ 'w', 'W', /* X 88 */ 'x', 'X', /* Y 89 */ 'y', 'Y', /* Z 90 */ 'z', 'Z', /* 91 */ 0, 0, /* 92 */ 0, 0, /* 93 */ 0, 0, /* 94 */ 0, 0, /* 95 */ 0, 0, /* 96 96 */ '0', 0, /* 97 */ '1', 0, /* 98 */ '2', 0, /* 99 */ '3', 0, /* 100*/ '4', 0, /* 101*/ '5', 0, /* 102*/ '6', 0, /* 103*/ '7', 0, /* 104*/ '8', 0, /* 105*/ '9', 0, /* 106*/ '*', 0, /* 107*/ '+', 0, /* 108*/ 0, 0, /* 109*/ '-', 0, /* 110*/ '.', 0, /* 111*/ '/', 0, /* 112 112*/ 0, 0, /* 113*/ 0, 0, /* 114*/ 0, 0, /* 115*/ 0, 0, /* 116*/ 0, 0, /* 117*/ 0, 0, /* 118*/ 0, 0, /* 119*/ 0, 0, /* 120*/ 0, 0, /* 121*/ 0, 0, /* 122*/ 0, 0, /* 123*/ 0, 0, /* 124*/ 0, 0, /* 125*/ 0, 0, /* 126*/ 0, 0, /* 127*/ 0, 0, /* 128 128*/ 0, 0, /* 129*/ 0, 0, /* 130*/ 0, 0, /* 131*/ 0, 0, /* 132*/ 0, 0, /* 133*/ 0, 0, /* 134*/ 0, 0, /* 135*/ 0, 0, /* 136*/ 0, 0, /* 137*/ 0, 0, /* 138*/ 0, 0, /* 139*/ 0, 0, /* 140*/ 0, 0, /* 141*/ 0, 0, /* 142*/ 0, 0, /* 143*/ 0, 0, /* 144 144*/ 0, 0, /* 145*/ 0, 0, /* 146*/ 0, 0, /* 147*/ 0, 0, /* 148*/ 0, 0, /* 149*/ 0, 0, /* 150*/ 0, 0, /* 151*/ 0, 0, /* 152*/ 0, 0, /* 153*/ 0, 0, /* 154*/ 0, 0, /* 155*/ 0, 0, /* 156*/ 0, 0, /* 157*/ 0, 0, /* 158*/ 0, 0, /* 159*/ 0, 0, /* 160 160*/ 0, 0, /* 161*/ 0, 0, /* 162*/ 0, 0, /* 163*/ 0, 0, /* 164*/ 0, 0, /* 165*/ 0, 0, /* 166*/ 0, 0, /* 167*/ 0, 0, /* 168*/ 0, 0, /* 169*/ 0, 0, /* 170*/ 0, 0, /* 171*/ 0, 0, /* 172*/ 0, 0, /* 173*/ 0, 0, /* 174*/ 0, 0, /* 175*/ 0, 0, /* 176 176*/ 0, 0, /* 177*/ 0, 0, /* 178*/ 0, 0, /* 179*/ 0, 0, /* 180*/ '´', '¨', /* 181*/ 0, 0, /* 182*/ 0, 0, /* 183*/ 0, 0, /* 184*/ 0, 0, /* 185*/ 0, 0, /* 186*/ ';', ':', /* 187*/ '¡', '¿', /* 188*/ ',', ';', /* 189*/ '\'', '?', /* 190*/ '.', ':', /* 191*/ '/', '?', /* 192 192*/ 'º', 'ª', /* 193*/ 0, 0, /* 194*/ 0, 0, /* 195*/ 0, 0, /* 196*/ 0, 0, /* 197*/ 0, 0, /* 198*/ 0, 0, /* 199*/ 0, 0, /* 200*/ '-', '_', /* 201*/ 0, 0, /* 202*/ 0, 0, /* 203*/ 0, 0, /* 204*/ 0, 0, /* 205*/ 0, 0, /* 206*/ 0, 0, /* 207*/ 0, 0, /* 208 208*/ 0, 0, /* 209*/ 0, 0, /* 210*/ 0, 0, /* 211*/ 0, 0, /* 212*/ 0, 0, /* 213*/ 0, 0, /* 214*/ 0, 0, /* 215*/ 0, 0, /* 216*/ 0, 0, /* 217*/ 0, 0, /* 218*/ 0, 0, /* 219*/ '`', '^', /* 220*/ 'ç', 'Ç', /* 221*/ '+', '*', /* 222*/ '\'', '"', /* 223*/ 0, 0, /* 224 224*/ 0, 0, /* 225*/ 0, 0, /* 226*/ 0, 0, /* 227*/ 0, 0, /* 228*/ 0, 0, /* 229*/ 0, 0, /* 230*/ 0, 0, /* 231*/ 'ç', 'Ç', /* 232*/ 0, 0, /* 233*/ 0, 0, /* 234*/ 0, 0, /* 235*/ 0, 0, /* 236*/ 0, 0, /* 237*/ 0, 0, /* 238*/ 0, 0, /* 239*/ 0, 0, /* 240 240*/ 0, 0, /* 241*/ 'ñ', 'Ñ', /* 242*/ 0, 0, /* 243*/ 0, 0, /* 244*/ 0, 0, /* 245*/ 0, 0, /* 246*/ 0, 0, /* 247*/ 0, 0, /* 248*/ 0, 0, /* 249*/ 0, 0, /* 250*/ 0, 0, /* 251*/ 0, 0, /* 252*/ 0, 0, /* 253*/ 0, 0, /* 254*/ 0, 0, /* 255*/ 0, 0, }; uicKeyTable uicItalianKeyEntryTable[KEY_TOTAL_KEYS] = { /* 0 0 */ 0, 0, /* 1 */ 0, 0, /* 2 */ 0, 0, /* 3 */ 0, 0, /* 4 */ 0, 0, /* 5 */ 0, 0, /* 6 */ 0, 0, /* 7 */ 0, 0, /* 8 */ 0, 0, /* 9 */ 0, 0, /* 10 */ 0, 0, /* 11 */ 0, 0, /* 12 */ 0, 0, /* 13 */ 0, 0, /* 14 */ 0, 0, /* 15 */ 0, 0, /* 16 16 */ 0, 0, /* 17 */ 0, 0, /* 18 */ 0, 0, /* 19 */ 0, 0, /* 20 */ 0, 0, /* 21 */ 0, 0, /* 22 */ 0, 0, /* 23 */ 0, 0, /* 24 */ 0, 0, /* 25 */ 0, 0, /* 26 */ 0, 0, /* 27 */ 0, 0, /* 28 */ 0, 0, /* 29 */ 0, 0, /* 30 */ 0, 0, /* 31 */ 0, 0, /* space 32 32 */ ' ', ' ', /* 33 */ 0, 0, /* 34 */ 0, 0, /* 35 */ 0, 0, /* 36 */ 0, 0, /* 37 */ 0, 0, /* 38 */ 0, 0, /* punctuation 39 */ 0, 0, /* 40 */ 0, 0, /* 41 */ 0, 0, /* 42 */ 0, 0, /* 43 */ 0, 0, /* 44 */ 0, 0, /* 45 */ '-', '_', /* 46 */ 0, 0, /* 47 */ 0, 0, /* 0 48 48 */ '0', '=', /* 1 49 */ '1', '!', /* 2 50 */ '2', '"', /* 3 51 */ '3', '£', /* 4 52 */ '4', '$', /* 5 53 */ '5', '%', /* 6 54 */ '6', '&', /* 7 55 */ '7', '/', /* 8 56 */ '8', '(', /* 9 57 */ '9', ')', /* : 58 */ ':', 0, /* ; 59 */ ';', 0, /* < 60 */ '<', 0, /* = 61 */ '=', '+', /* > 62 */ '>', 0, /* ? 63 */ '?', 0, /* @ 64 64 */ '@', 0, /* A 65 */ 'a', 'A', /* B 66 */ 'b', 'B', /* C 67 */ 'c', 'C', /* D 68 */ 'd', 'D', /* E 69 */ 'e', 'E', /* F 70 */ 'f', 'F', /* G 71 */ 'g', 'G', /* H 72 */ 'h', 'H', /* I 73 */ 'i', 'I', /* J 74 */ 'j', 'J', /* K 75 */ 'k', 'K', /* L 76 */ 'l', 'L', /* M 77 */ 'm', 'M', /* N 78 */ 'n', 'N', /* O 79 */ 'o', 'O', /* P 80 80 */ 'p', 'P', /* Q 81 */ 'q', 'Q', /* R 82 */ 'r', 'R', /* S 83 */ 's', 'S', /* T 84 */ 't', 'T', /* U 85 */ 'u', 'U', /* V 86 */ 'v', 'V', /* W 87 */ 'w', 'W', /* X 88 */ 'x', 'X', /* Y 89 */ 'y', 'Y', /* Z 90 */ 'z', 'Z', /* 91 */ 0, 0, /* 92 */ 0, 0, /* 93 */ 0, 0, /* 94 */ 0, 0, /* 95 */ 0, 0, /* 96 96 */ '0', 0, /* 97 */ '1', 0, /* 98 */ '2', 0, /* 99 */ '3', 0, /* 100*/ '4', 0, /* 101*/ '5', 0, /* 102*/ '6', 0, /* 103*/ '7', 0, /* 104*/ '8', 0, /* 105*/ '9', 0, /* 106*/ '*', 0, /* 107*/ '+', 0, /* 108*/ 0, 0, /* 109*/ '-', 0, /* 110*/ '.', 0, /* 111*/ '/', 0, /* 112 112*/ 0, 0, /* 113*/ 0, 0, /* 114*/ 0, 0, /* 115*/ 0, 0, /* 116*/ 0, 0, /* 117*/ 0, 0, /* 118*/ 0, 0, /* 119*/ 0, 0, /* 120*/ 0, 0, /* 121*/ 0, 0, /* 122*/ 0, 0, /* 123*/ 0, 0, /* 124*/ 0, 0, /* 125*/ 0, 0, /* 126*/ 0, 0, /* 127*/ 0, 0, /* 128 128*/ 0, 0, /* 129*/ 0, 0, /* 130*/ 0, 0, /* 131*/ 0, 0, /* 132*/ 0, 0, /* 133*/ 0, 0, /* 134*/ 0, 0, /* 135*/ 0, 0, /* 136*/ 0, 0, /* 137*/ 0, 0, /* 138*/ 0, 0, /* 139*/ 0, 0, /* 140*/ 0, 0, /* 141*/ 0, 0, /* 142*/ 0, 0, /* 143*/ 0, 0, /* 144 144*/ 0, 0, /* 145*/ 0, 0, /* 146*/ 0, 0, /* 147*/ 0, 0, /* 148*/ 0, 0, /* 149*/ 0, 0, /* 150*/ 0, 0, /* 151*/ 0, 0, /* 152*/ 0, 0, /* 153*/ 0, 0, /* 154*/ 0, 0, /* 155*/ 0, 0, /* 156*/ 0, 0, /* 157*/ 0, 0, /* 158*/ 0, 0, /* 159*/ 0, 0, /* 160 160*/ 0, 0, /* 161*/ 0, 0, /* 162*/ 0, 0, /* 163*/ 0, 0, /* 164*/ 0, 0, /* 165*/ 0, 0, /* 166*/ 0, 0, /* 167*/ 0, 0, /* 168*/ 0, 0, /* 169*/ 0, 0, /* 170*/ 0, 0, /* 171*/ 0, 0, /* 172*/ 0, 0, /* 173*/ 0, 0, /* 174*/ 0, 0, /* 175*/ 0, 0, /* 176 176*/ 0, 0, /* 177*/ 0, 0, /* 178*/ 0, 0, /* 179*/ 0, 0, /* 180*/ 0, 0, /* 181*/ 0, 0, /* 182*/ 0, 0, /* 183*/ 0, 0, /* 184*/ 0, 0, /* 185*/ 0, 0, /* 186*/ ';', ':', /* 187*/ 'ì', '^', /* 188*/ ',', ';', /* 189*/ '\'', '?', /* 190*/ '.', ':', /* 191*/ '/', '?', /* 192 192*/ '\\', '|', /* 193*/ 0, 0, /* 194*/ 0, 0, /* 195*/ 0, 0, /* 196*/ 0, 0, /* 197*/ 0, 0, /* 198*/ 0, 0, /* 199*/ 0, 0, /* 200*/ '-', '_', /* 201*/ 0, 0, /* 202*/ 0, 0, /* 203*/ 0, 0, /* 204*/ 0, 0, /* 205*/ 0, 0, /* 206*/ 0, 0, /* 207*/ 0, 0, /* 208 208*/ 0, 0, /* 209*/ 0, 0, /* 210*/ 0, 0, /* 211*/ 0, 0, /* 212*/ 0, 0, /* 213*/ 0, 0, /* 214*/ 0, 0, /* 215*/ 0, 0, /* 216*/ 0, 0, /* 217*/ 0, 0, /* 218*/ 0, 0, /* 219*/ 'è', 'é', /* 220*/ 'ù', '§', /* 221*/ '+', '*', /* 222*/ 'à', '°', /* 223*/ 0, 0, /* 224 224*/ 0, 0, /* 225*/ 0, 0, /* 226*/ 0, 0, /* 227*/ 0, 0, /* 228*/ 0, 0, /* 229*/ 0, 0, /* 230*/ 0, 0, /* 231*/ 0, 0, /* 232*/ 0, 0, /* 233*/ 0, 0, /* 234*/ 0, 0, /* 235*/ 0, 0, /* 236*/ 0, 0, /* 237*/ 0, 0, /* 238*/ 0, 0, /* 239*/ 0, 0, /* 240 240*/ 0, 0, /* 241*/ 'ò', 'ç', /* 242*/ 0, 0, /* 243*/ 0, 0, /* 244*/ 0, 0, /* 245*/ 0, 0, /* 246*/ 0, 0, /* 247*/ 0, 0, /* 248*/ 0, 0, /* 249*/ 0, 0, /* 250*/ 0, 0, /* 251*/ 0, 0, /* 252*/ 0, 0, /* 253*/ 0, 0, /* 254*/ 0, 0, /* 255*/ 0, 0, }; sdword uicListWindowMargin = 6; /*============================================================================= Mouse/Keyboard focus: =============================================================================*/ bool uicMouseFocus = TRUE; sdword uicMouseSavedX = 0, uicMouseSavedY = 0; #define UIC_MOUSE_MOVED_X (uicMouseSavedX != mouseCursorXPosition) #define UIC_MOUSE_MOVED_Y (uicMouseSavedY != mouseCursorYPosition) #define UIC_MOUSE_MOVED (UIC_MOUSE_MOVED_X || UIC_MOUSE_MOVED_Y) void uicFocusToKeyboard(void) { if (uicMouseFocus) { uicMouseFocus = FALSE; uicMouseSavedX = mouseCursorXPosition; uicMouseSavedY = mouseCursorYPosition; } } void uicFocusToMouse(regionhandle region) { if (UIC_MOUSE_MOVED) { if (mouseInRectGeneral(region->rect.x0, region->rect.y0, region->rect.x1, region->rect.y1)) { uicMouseFocus = TRUE; /* uicClearCurrent(region); feTabStop = region->tabstop; uicSetCurrent(region, FALSE);*/ } } } /*============================================================================= Private functions: =============================================================================*/ #if UIC_TEST extern regionhandle ghMainRegion; sdword uicTestProcess(regionhandle region, sdword ID, udword event, udword data) { dbgMessagef("\nUI test function region = 0x%x, ID = %d, event = 0x%x, data = %d", region, ID, event, data); return(0); } #endif //UIC_TEST /*----------------------------------------------------------------------------- Name : colAdjust Description : adjust a color's v component by amount (+ or -) Inputs : c - the color the adjust, amount - adjustment Outputs : c is modified Return : ----------------------------------------------------------------------------*/ void colAdjust(color *c, sword amount) { real32 r, g, b; real32 h, s, v; ubyte ir, ig, ib; r = colUbyteToReal(colRed(*c)); g = colUbyteToReal(colGreen(*c)); b = colUbyteToReal(colBlue(*c)); colRGBToHSV(&h, &s, &v, r, g, b); if (amount > 0) v += colUbyteToReal(amount); else v += -colUbyteToReal(-amount); if (v > (real32)1.0) v = (real32)1.0; else if (v < (real32)0.0) v = (real32)0.0; colHSVToRGB(&r, &g, &b, h, s, v); ir = colRealToUbyte(r); ig = colRealToUbyte(g); ib = colRealToUbyte(b); *c = colRGB(ir, ig, ib); } //draw a button void uicButtonDraw(regionhandle reg) { featom* atom; if ((feStack[feStackIndex].screen!=NULL) && (feStack[feStackIndex].screen != ((buttonhandle)reg)->screen) ) { if ((reg->parent!=ghMainRegion) || (feStackIndex>0)) { ferDrawButton(reg->rect, b_off); return; } } if (!uicMouseFocus) uicFocusToMouse(reg); atom = (featom*)reg->atom; if (atom != NULL && glCapFeatureExists(GL_SWAPFRIENDLY)) { color c; rectangle r; r = reg->rect; r.y1++; if (bitTest(atom->flags, FAF_Background)) { c = FEC_Background; } else { c = colBlack; } primRectSolid2(&r, c); } if (bitTest(reg->status, RSF_RegionDisabled)) { ferDrawButton(reg->rect, b_off_disabled); } else if (bitTest(reg->status, RSF_LeftPressed)) { if (bitTest(reg->status, RSF_MouseInside)) { ferDrawButton(reg->rect, b_on_focus_mouse); } else { ferDrawButton(reg->rect, b_off_focus_mouse); } } else if (bitTest(reg->status, RSF_CurrentSelected)) { if (bitTest(reg->status, RSF_MouseInside)) { ferDrawButton(reg->rect, b_off_focus_mouse); } else { ferDrawButton(reg->rect, b_off_focus); } } else if (bitTest(reg->status, RSF_MouseInside)) { ferDrawButton(reg->rect, b_off_mouse); } else { ferDrawButton(reg->rect, b_off); } } /*----------------------------------------------------------------------------- Name : uicButtonProcess Description : Region processor callback for buttons Inputs : region - region to handle processing ID - user-assigned ID of button event - enumeration of event to be processed data - additional event data (message specific) Outputs : calls through to button handler function if button released Return : flags indicating further operation: Note : can call user function with any region message if filter set up properly. ----------------------------------------------------------------------------*/ bool uicButtonReleased = FALSE; udword uicButtonProcess(regionhandle region, sdword ID, udword event, udword data) { udword mask = 0; #ifndef HW_Release udword i; featom *atom = (featom *)region->atom; #endif switch (event) { case RPE_PressLeft: uicClearCurrent(region); uicSetCurrent(region, FALSE); soundEvent(NULL, UI_Click); mask |= RPR_Redraw; #ifndef HW_Release dbgMessagef("\nEn: %c Fr: %c De: %c Es: %c It: %c", atom->hotKey[0], atom->hotKey[1], atom->hotKey[2], atom->hotKey[3], atom->hotKey[4]); #endif break; case RPE_KeyDown: soundEvent(NULL, UI_Click); //fall through case RPE_ReleaseLeft: uicButtonReleased = TRUE; ((buttonhandle)region)->processFunction(region, ID, CM_ButtonClick, 0); uicButtonReleased = FALSE; mask |= RPR_Redraw; break; case RPE_Enter: case RPE_Exit: case RPE_ExitHoldLeft: mask |= RPR_Redraw; break; } if (mask != 0) { regRecursiveSetDirty(region); } return(mask); } /*----------------------------------------------------------------------------- Name : uicToggleDraw Description : Draw a toggle button Inputs : reg - region representing toggle Outputs : Return : ----------------------------------------------------------------------------*/ void uicToggleDraw(regionhandle reg) { featom* atom; /* rectangle erase; erase = reg->rect; //erase the background to get rid of text that might be there erase.y0 += 3; erase.x0 += 3; erase.x1 -= 3; */ //primRectSolid2(&erase, colBlack); if (feStack[feStackIndex].screen != ((buttonhandle)reg)->screen) { //if a button on a different screen ferDrawButton(reg->rect, tb_off); //draw it normally return; } if (!uicMouseFocus) uicFocusToMouse(reg); atom = (featom*)reg->atom; if (atom != NULL && glCapFeatureExists(GL_SWAPFRIENDLY)) { color c; rectangle r; r = reg->rect; r.y1++; if (bitTest(atom->flags, FAF_Background)) { c = FEC_Background; } else { c = colBlack; } primRectSolid2(&r, c); } if (bitTest(reg->status, RSF_RegionDisabled)) { if (FECHECKED(((featom *)reg->userID))) ferDrawButton(reg->rect, tb_on_disabled); else ferDrawButton(reg->rect, tb_off_disabled); } else { if (FECHECKED(((featom *)reg->userID))) { if (bitTest(reg->status, RSF_LeftPressed)) { if (bitTest(reg->status, RSF_MouseInside)) { ferDrawButton(reg->rect, tb_on_focus_mouse); } else { ferDrawButton(reg->rect, tb_on_focus); } } else if (bitTest(reg->status, RSF_CurrentSelected)) { if (bitTest(reg->status, RSF_MouseInside)) { ferDrawButton(reg->rect, tb_on_focus_mouse); } else { ferDrawButton(reg->rect, tb_on_focus); } } else if (bitTest(reg->status, RSF_MouseInside)) { ferDrawButton(reg->rect, tb_on_mouse); } else { ferDrawButton(reg->rect, tb_on); } } else { if (bitTest(reg->status, RSF_LeftPressed)) { if (bitTest(reg->status, RSF_MouseInside)) { ferDrawButton(reg->rect, tb_off_focus_mouse); } else { ferDrawButton(reg->rect, tb_off_focus); } } else if (bitTest(reg->status, RSF_CurrentSelected)) { if (bitTest(reg->status, RSF_MouseInside)) { ferDrawButton(reg->rect, tb_off_focus_mouse); } else { ferDrawButton(reg->rect, tb_off_focus); } } else if (bitTest(reg->status, RSF_MouseInside)) { ferDrawButton(reg->rect, tb_off_mouse); } else { ferDrawButton(reg->rect, tb_off); } } } /* color c, ForeColor; bool8 checked; sdword width; uword cloops; if (!uicMouseFocus) uicFocusToMouse(reg); checked = (bool8)((bitTest(((featom *)reg->userID)->flags, FAF_Checked)) ? TRUE : FALSE); // a toggle button is a normal button that retains it's on state if it is toggled if (fetEnableTextures) { if (bitTest(reg->status, RSF_LeftPressed) && bitTest(reg->status, RSF_MouseInside)) { ferDrawButton(reg->rect, on); } else if (checked) { ferDrawButton(reg->rect, mouse); } else { if ( ( (!uicMouseFocus) && (bitTest(reg->status, RSF_CurrentSelected)) ) || ( (uicMouseFocus) && (bitTest(reg->status, RSF_MouseInside )) ) ) { ferDrawButton(reg->rect, mouse); } else { ferDrawButton(reg->rect, off); } } return; } c = ((buttonhandle)reg)->contentColor; width = 2; if ((bitTest(reg->status, RSF_LeftPressed) && bitTest(reg->status, RSF_MouseInside))) { colAdjust(&c, 64); } else if (bitTest(reg->status, RSF_CurrentSelected)) { colAdjust(&c, 32); } else if (checked) { colAdjust(&c, 16); } primBeveledRectSolid(®->rect, c, 3, 3); ForeColor = ((buttonhandle)reg)->borderColor; cloops = (bool8)(checked ? 7 : 3); colAdjust(&ForeColor, 64); primSeriesOfRoundRects(®->rect, 1, ForeColor, c, cloops, 2, 2);*/ } /*----------------------------------------------------------------------------- Name : uicToggleProcess Description : Region processor callback for toggle buttons Inputs : region - region to handle processing ID - user-assigned ID of button event - enumeration of event to be processed data - additional event data (message specific) Outputs : calls through to button handler function if button released, toggles state of reg->atom->flags.FAF_Checked Return : flags indicating further operation: Note : can call user function with any region message if filter set up properly. ----------------------------------------------------------------------------*/ udword uicToggleProcess(regionhandle region, sdword ID, udword event, udword data) { udword mask = 0; switch (event) { case RPE_PressLeft: uicClearCurrent(region); uicSetCurrent(region, FALSE); soundEvent(NULL, UI_Click); mask |= RPR_Redraw; break; case RPE_ReleaseLeft: bitToggle(((featom *)region->userID)->status, FAS_Checked); ((buttonhandle)region)->processFunction(region, ID, CM_ButtonClick, 0); mask |= RPR_Redraw; break; case RPE_KeyDown: soundEvent(NULL, UI_Click); bitToggle(((featom *)region->userID)->status, FAS_Checked); ((buttonhandle)region)->processFunction(region, ID, CM_ButtonClick, 0); mask |= RPR_Redraw; break; case RPE_Enter: case RPE_Exit: case RPE_ExitHoldLeft: mask |= RPR_Redraw; break; } if (mask != 0) { regRecursiveSetDirty(region); } return(mask); } /*----------------------------------------------------------------------------- Name : uicRadioButtonProcess Description : Region processor callback for radio buttons Inputs : region - region to handle processing ID - user-assigned ID of button event - enumeration of event to be processed data - additional event data (message specific) Outputs : calls through to button handler function if button released, set reg->atom->flags.FAF_Checked, unset all other buttons in set Return : flags indicating further operation: Note : can call user function with any region message if filter set up properly. ----------------------------------------------------------------------------*/ udword uicRadioButtonProcess(regionhandle region, sdword ID, udword event, udword data) { udword mask = 0; featom *atom; switch (event) { case RPE_PressLeft: uicClearCurrent(region); uicSetCurrent(region, FALSE); soundEvent(NULL, UI_Click); mask |= RPR_Redraw; break; case RPE_KeyDown: case RPE_ReleaseLeft: ((buttonhandle)region)->processFunction(region, ID, CM_ButtonClick, 0); atom = (featom *)region->userID; //get this atom feRadioButtonSet(atom->name, (sdword)atom->pData); //set a certain radio button if (event == RPE_KeyDown) soundEvent(NULL, UI_Click); mask |= RPR_Redraw; break; case RPE_Enter: case RPE_Exit: case RPE_ExitHoldLeft: mask |= RPR_Redraw; break; } if (mask != 0) { regRecursiveSetDirty(region); } return(mask); } //process scrollbar messages udword uicScrollBarProcess(regionhandle region, sdword ID, udword event, udword data) { scrollbarhandle shandle; udword mask = 0,x,y; switch (ID) { case UIC_ScrollbarTab: shandle = (scrollbarhandle)region; switch (event) { case RPE_ReleaseLeft: shandle->processFunction(region, ID, CM_ButtonClick, shandle->clickType); mask |= RPR_Redraw; break; case RPE_WheelUp: shandle->processFunction(region, ID, CM_ButtonClick, SC_Negative); mask |= RPR_Redraw; break; case RPE_WheelDown: shandle->processFunction(region, ID, CM_ButtonClick, SC_Positive); mask |= RPR_Redraw; break; case RPE_PressLeft: if (mouseInRect(&shandle->thumb)) { shandle->clickType = SC_Thumb; shandle->mouseX = scThumbRelativeX(shandle); shandle->mouseY = scThumbRelativeY(shandle); } else { soundEvent(NULL, UI_Click); shandle->clickType = SC_Other; shandle->mouseX = scRelativeX(shandle); shandle->mouseY = scRelativeY(shandle); } mask |= RPR_Redraw; break; case RPE_EnterHoldLeft: shandle->clickType = SC_Thumb; mask |= RPR_Redraw; break; case RPE_HoldLeft: if (shandle->clickType == SC_Thumb) { x = (udword)scThumbRelativeX(shandle); y = (udword)scThumbRelativeY(shandle); shandle->processFunction(region, ID, CM_ThumbMoved, (x << 16) | y); } mask |= RPR_Redraw; break; case RPE_Enter: case RPE_Exit: case RPE_ExitHoldLeft: mask |= RPR_Redraw; break; #if 0 default: shandle->clickType = SC_NoRegion; #endif } break; case UIC_ScrollbarUpButton: case UIC_ScrollbarDownButton: shandle = ((scrollbarbuttonhandle)region)->scrollbar; switch (event) { case RPE_ReleaseLeft: if (ID==UIC_ScrollbarUpButton) shandle->processFunction(region, ID, CM_ButtonClick, SC_Negative); else shandle->processFunction(region, ID, CM_ButtonClick, SC_Positive); mask |= RPR_Redraw; break; case RPE_WheelUp: shandle->processFunction(region, ID, CM_ButtonClick, SC_Negative); mask |= RPR_Redraw; break; case RPE_WheelDown: shandle->processFunction(region, ID, CM_ButtonClick, SC_Positive); mask |= RPR_Redraw; break; case RPE_PressLeft: mask |= RPR_Redraw; break; case RPE_EnterHoldLeft: case RPE_HoldLeft: case RPE_Enter: case RPE_Exit: case RPE_ExitHoldLeft: mask |= RPR_Redraw; break; } break; // soundEvent(NULL, Click); break; } if (mask != 0) { regRecursiveSetDirty(region); } return mask; } /*----------------------------------------------------------------------------- Name : uicScrollBarDraw Description : Draw a scrollbar Inputs : reg - region representing scrollbar Outputs : Return : ----------------------------------------------------------------------------*/ void uicScrollBarDraw(regionhandle reg) { scrollbarhandle shandle = (scrollbarhandle)reg; if (feStack[feStackIndex].screen != shandle->screen) { ferDrawScrollbar(shandle, s_off); return; } if (bitTest(reg->status,RSF_LeftPressed)) { if (bitTest(reg->status, RSF_MouseInside)) { ferDrawScrollbar(shandle, s_on_mouse); return; } else { ferDrawScrollbar(shandle, s_off_mouse); return; } } else { if (bitTest(reg->status, RSF_MouseInside)) { ferDrawScrollbar(shandle, s_off_mouse); return; } } ferDrawScrollbar(shandle, s_off); } /*----------------------------------------------------------------------------- Name : uicScrollBarButtonDraw Description : Draws the button for the scroll bar Inputs : reg - region for the scrollbar button Outputs : Return : void ----------------------------------------------------------------------------*/ void uicScrollBarButtonDraw(regionhandle reg) { if (feStack[feStackIndex].screen != ((scrollbarbuttonhandle)reg)->scrollbar->screen) { if (reg->userID==UIC_ScrollbarUpButton) ferDrawScrollbarButton(reg, sub_off); else if (reg->userID==UIC_ScrollbarDownButton) ferDrawScrollbarButton(reg, sdb_off); return; } if (bitTest(reg->status,RSF_LeftPressed)) { if (bitTest(reg->status, RSF_MouseInside)) { if (reg->userID==UIC_ScrollbarUpButton) ferDrawScrollbarButton(reg, sub_on_mouse); else if (reg->userID==UIC_ScrollbarDownButton) ferDrawScrollbarButton(reg, sdb_on_mouse); return; } else { if (reg->userID==UIC_ScrollbarUpButton) ferDrawScrollbarButton(reg, sub_off_mouse); else if (reg->userID==UIC_ScrollbarDownButton) ferDrawScrollbarButton(reg, sdb_off_mouse); return; } } else { if (bitTest(reg->status, RSF_MouseInside)) { if (reg->userID==UIC_ScrollbarUpButton) ferDrawScrollbarButton(reg, sub_off_mouse); else if (reg->userID==UIC_ScrollbarDownButton) ferDrawScrollbarButton(reg, sdb_off_mouse); return; } } if (reg->userID==UIC_ScrollbarUpButton) ferDrawScrollbarButton(reg, sub_off); else if (reg->userID==UIC_ScrollbarDownButton) ferDrawScrollbarButton(reg, sdb_off); } void uicListItemSelectedDraw(rectangle* rect) { rectangle r = *rect; r.x0 -= 2; r.x1++; r.y1--; primRectTranslucent2(&r, FEC_ListItemTranslucent); primRectOutline2(&r, 1, FEC_ListItemTranslucentBorder); } /*----------------------------------------------------------------------------- Name : uicListWindowDraw Description : draws the list window by doing the callbacks for each line Inputs : region Outputs : none Return : void ----------------------------------------------------------------------------*/ void uicListWindowDraw(regionhandle reg) { listwindowhandle listhandle; listitemhandle item; rectangle rect=reg->rect; //, erase; Node *walk; sdword count=0; listhandle = (listwindowhandle)reg; /* if (listhandle->windowflags&UICLW_JustRedrawTitle) { bitClear(listhandle->windowflags,UICLW_JustRedrawTitle); rect.y1 = rect.y0+listhandle->TitleHeight; erase = rect; erase.y0 += 3; erase.x0 += 3; erase.x1 -= 3; if (listhandle->windowflags&UICLW_HasTitleBar) { primRectSolid2(&erase, colBlack); dbgAssert(listhandle->titledraw!=NULL); listhandle->titledraw(&rect); } } else {*/ rect.x0+=uicListWindowMargin; rect.y0+=uicListWindowMargin; rect.x1-=uicListWindowMargin; rect.y1-=uicListWindowMargin; primRectSolid2(®->rect, FEC_Background); if (bitTest(reg->status,RSF_CurrentSelected)) ferDrawFocusWindow(reg, lw_focus); else ferDrawFocusWindow(reg, lw_normal); primRectSolid2(&rect, FEC_Background); rect.y1 = rect.y0+listhandle->TitleHeight; if (listhandle->windowflags&UICLW_HasTitleBar) { listhandle->titledraw(&rect); } rect.y0 = reg->rect.y0+listhandle->TitleHeight+uicListWindowMargin; rect.y1 = rect.y0+listhandle->itemheight; if (listhandle->topitem!=NULL) walk = &listhandle->topitem->link; else walk = NULL; while ( (walk!=NULL) && (countMaxIndex) ) { item = (listitemhandle)listGetStructOfNode(walk); dbgAssert(listhandle->itemdraw!=NULL); listhandle->itemdraw((rectangle *)&rect, item); if (bitTest(item->flags, UICLI_Selected)) { uicListItemSelectedDraw(&rect); } rect.y0 = rect.y0+listhandle->itemheight; rect.y1 = rect.y0+listhandle->itemheight; count++; walk = walk->next; } // } } /*----------------------------------------------------------------------------- Name : uicListScrollBarAdjust Description : resizes the list window scrollbar if an item is added or removed Inputs : list window handle Outputs : Return : void ----------------------------------------------------------------------------*/ void uicListScrollBarAdjust(listwindowhandle listwindow) { if (listwindow->UpperIndex > listwindow->ListTotal) { listwindow->UpperIndex = listwindow->MaxIndex; } scAdjustThumbwheel(listwindow->scrollbar, (uword)listwindow->UpperIndex, (uword)listwindow->MaxIndex, (uword)listwindow->ListTotal); } /*----------------------------------------------------------------------------- Name : uicListGetItemClicked Description : returns the item clicked on or NULL if no item clicked on. Inputs : listwindow, mouse y position Outputs : list item handle Return : list item ----------------------------------------------------------------------------*/ listitemhandle uicListGetItemClicked(listwindowhandle listhandle, sdword yClicked) { sdword y=listhandle->reg.rect.y0; listitemhandle item; Node *walk; sdword count=0; y += listhandle->TitleHeight+uicListWindowMargin; if (listhandle->topitem!=NULL) walk = &listhandle->topitem->link; else walk = NULL; while ( (walk!=NULL) && (countMaxIndex) ) { if (yClicked < y + listhandle->itemheight) { break; } y += listhandle->itemheight; count++; walk = walk->next; } if (walk == NULL) return (NULL); item = (listitemhandle)listGetStructOfNode(walk); if (item->flags&UICLI_CanSelect) return (item); else return (NULL); } /*============================================================================= These next series of functions are for processing the list window cursor keys. They are split up so that it is easier to understand and modify parts of them as needed. =============================================================================*/ void uicListWindowViewSelection(listwindowhandle listhandle) { sdword CurSelectedRelPos = uicListWindowRelativePos(listhandle); // bring the currently selected line into view, either by scrolling up or down. if (CurSelectedRelPos<0) { // must scroll up while (CurSelectedRelPos<0) { if (listhandle->topitem != NULL) { if (listhandle->topitem->link.prev!=NULL) { listhandle->topitem = listGetStructOfNode(listhandle->topitem->link.prev); listhandle->UpperIndex --; uicListScrollBarAdjust(listhandle); CurSelectedRelPos++; } } } } if (CurSelectedRelPos-listhandle->MaxIndex >= 0) { // must scroll down while (CurSelectedRelPos-listhandle->MaxIndex >= 0) { if (listhandle->topitem != NULL) { if (listhandle->topitem->link.next!=NULL) { listhandle->topitem = listGetStructOfNode(listhandle->topitem->link.next); listhandle->UpperIndex ++; uicListScrollBarAdjust(listhandle); CurSelectedRelPos--; } } } } } void uicListWindowCheckSel(listwindowhandle listhandle) { // make sure that the currently selected line can be selected. if (!bitTest(listhandle->CurLineSelected->flags,UICLI_CanSelect)) { while ( (!bitTest(listhandle->CurLineSelected->flags,UICLI_CanSelect)) && (listhandle->CurLineSelected->link.prev!=NULL)) { bitClear(listhandle->CurLineSelected->flags,UICLI_Selected); listhandle->CurLineSelected = listGetStructOfNode(listhandle->CurLineSelected->link.prev); bitSet(listhandle->CurLineSelected->flags,UICLI_Selected); } if (!bitTest(listhandle->CurLineSelected->flags,UICLI_CanSelect)) { listhandle->CurLineSelected = NULL; } } } void uicListWindowUpArrow(listwindowhandle listhandle) { Node *walk; listitemhandle item; // sdword relpos; if (bitTest(listhandle->windowflags,UICLW_CanSelect)) { // we can select items in this window if (listhandle->CurLineSelected != NULL) { if (listhandle->CurLineSelected->link.prev != NULL) { // we are not at the top of the list walk = listhandle->CurLineSelected->link.prev; item = listGetStructOfNode(walk); // while we havn't reached the top of the list and we can't select the item while ((walk != NULL)&&(!bitTest(item->flags, UICLI_CanSelect))) { item = listGetStructOfNode(walk); walk = walk->prev; // relpos--; } if (bitTest(item->flags, UICLI_CanSelect)) { // we have found an item we can actually select bitClear(listhandle->CurLineSelected->flags,UICLI_Selected); listhandle->CurLineSelected = item; bitSet(listhandle->CurLineSelected->flags,UICLI_Selected); uicListWindowViewSelection(listhandle); } } } else { // Nothing has been selected yet select something if we can. walk = listhandle->listofitems.head; while (walk != NULL) { item = listGetStructOfNode(walk); if (bitTest(item->flags, UICLI_CanSelect)) { listhandle->CurLineSelected = item; break; } walk = walk->next; } } } else { // this is easy just move the top display item up by one, no selections to worry about if (listhandle->topitem != NULL) { if (listhandle->topitem->link.prev!=NULL) { listhandle->topitem = listGetStructOfNode(listhandle->topitem->link.prev); listhandle->UpperIndex --; uicListScrollBarAdjust(listhandle); } } } } void uicListWindowDownArrow(listwindowhandle listhandle) { Node *walk; listitemhandle item; // sdword relpos; if (bitTest(listhandle->windowflags,UICLW_CanSelect)) { // we can select items in this window if (listhandle->CurLineSelected != NULL) { if (listhandle->CurLineSelected->link.next!=NULL) { // we are not at the bottom of the list so ... walk = listhandle->CurLineSelected->link.next; item = listGetStructOfNode(walk); // while we havnt hit the bottom, and we can't select the current item while ( (walk != NULL)&&(!bitTest(item->flags, UICLI_CanSelect)) ) { item = listGetStructOfNode(walk); walk = walk->next; // relpos++; } if (bitTest(item->flags, UICLI_CanSelect)) { bitClear(listhandle->CurLineSelected->flags,UICLI_Selected); listhandle->CurLineSelected = item; bitSet(listhandle->CurLineSelected->flags,UICLI_Selected); uicListWindowViewSelection(listhandle); } } } else { // Nothing has been selected yet select something if we can. walk = listhandle->listofitems.head; while (walk != NULL) { item = listGetStructOfNode(walk); if (bitTest(item->flags, UICLI_CanSelect)) { listhandle->CurLineSelected = item; break; } walk = walk->next; } } } else { // this is easy just move the top display item down by one, no selections to worry about if ( (listhandle->topitem != NULL) && (listhandle->UpperIndex < listhandle->ListTotal - listhandle->MaxIndex) ) { if (listhandle->topitem->link.next!=NULL) { listhandle->topitem = listGetStructOfNode(listhandle->topitem->link.next); listhandle->UpperIndex ++; uicListScrollBarAdjust(listhandle); } } } } void uicListWindowHome(listwindowhandle listhandle) { // just move the selection and display item to the top of the list. if (listhandle->listofitems.head!=NULL) { listhandle->topitem = listGetStructOfNode(listhandle->listofitems.head); listhandle->UpperIndex = 0; if (bitTest(listhandle->windowflags,UICLW_CanSelect)) { bitClear(listhandle->CurLineSelected->flags,UICLI_Selected); listhandle->CurLineSelected = listGetStructOfNode(listhandle->listofitems.head); bitSet(listhandle->CurLineSelected->flags,UICLI_Selected); } uicListScrollBarAdjust(listhandle); } } void uicListWindowEnd(listwindowhandle listhandle) { Node *walk; listitemhandle item; sdword end, i; // just move the selection to the bottom of the list, and the display so that all of the // items are on the screen with the selected one at the bottom. if (listhandle->listofitems.tail!=NULL) { if (listhandle->ListTotal > listhandle->MaxIndex) { end = listhandle->MaxIndex-1; walk = listhandle->listofitems.tail; for (i=0;iprev; } listhandle->topitem = listGetStructOfNode(walk); listhandle->UpperIndex = listhandle->ListTotal - listhandle->MaxIndex; uicListScrollBarAdjust(listhandle); // if can select items in the list window at all, if not don't waste the time searching if (bitTest(listhandle->windowflags,UICLW_CanSelect)) { walk = listhandle->listofitems.tail; item = listGetStructOfNode(walk); while ((walk != NULL)&&(!bitTest(item->flags,UICLI_CanSelect))) { item = listGetStructOfNode(walk); walk = walk->prev; } if (bitTest(item->flags,UICLI_CanSelect)) { bitClear(listhandle->CurLineSelected->flags,UICLI_Selected); listhandle->CurLineSelected = item; bitSet(listhandle->CurLineSelected->flags,UICLI_Selected); } uicListWindowCheckSel(listhandle); } } else { // if can select items in the list window at all, if not don't waste the time searching if (bitTest(listhandle->windowflags,UICLW_CanSelect)) { walk = listhandle->listofitems.tail; item = listGetStructOfNode(walk); while ((walk != NULL)&&(!bitTest(item->flags,UICLI_CanSelect))) { item = listGetStructOfNode(walk); walk = walk->prev; } if (bitTest(item->flags,UICLI_CanSelect)) { bitClear(listhandle->CurLineSelected->flags,UICLI_Selected); listhandle->CurLineSelected = item; bitSet(listhandle->CurLineSelected->flags,UICLI_Selected); } uicListWindowCheckSel(listhandle); } } } } void uicListWindowPageUp(listwindowhandle listhandle) { listitemhandle item; sdword count,i; // this one is a pain in the ass. if (bitTest(listhandle->windowflags,UICLW_CanSelect)) { count = 0; if ( (listhandle->topitem != NULL) && (listhandle->UpperIndex > 0) ) { while ( (countMaxIndex) && (listhandle->UpperIndex >= 0)) { if (listhandle->topitem->link.prev!=NULL) { listhandle->topitem = listGetStructOfNode(listhandle->topitem->link.prev); listhandle->UpperIndex--; uicListScrollBarAdjust(listhandle); } else break; count++; } } if (listhandle->CurLineSelected!=NULL) { item = listGetStructOfNonPtrNode(listhandle->topitem->link); if (bitTest(item->flags,UICLI_CanSelect)) { bitClear(listhandle->CurLineSelected->flags,UICLI_Selected); listhandle->CurLineSelected = item; bitSet(listhandle->CurLineSelected->flags,UICLI_Selected); if (count < listhandle->MaxIndex) { if (count==0) { item = listGetStructOfNode(listhandle->listofitems.head); bitClear(listhandle->CurLineSelected->flags,UICLI_Selected); listhandle->CurLineSelected = item; bitSet(listhandle->CurLineSelected->flags,UICLI_Selected); return; } } i=0; do { if (listhandle->CurLineSelected->link.next!=NULL) { bitClear(listhandle->CurLineSelected->flags,UICLI_Selected); listhandle->CurLineSelected = listGetStructOfNode(listhandle->CurLineSelected->link.next); bitSet(listhandle->CurLineSelected->flags,UICLI_Selected); } i++; } while (itopitem != NULL) && (listhandle->UpperIndex > 0) ) { count = 0; while ( (countMaxIndex) && (listhandle->UpperIndex >= 0)) { if (listhandle->topitem->link.prev!=NULL) { listhandle->topitem = listGetStructOfNode(listhandle->topitem->link.prev); listhandle->UpperIndex--; uicListScrollBarAdjust(listhandle); } else break; count++; } } } } void uicListWindowPageDown(listwindowhandle listhandle) { listitemhandle item; sdword count,pos,i; Node *walk; // so is this one real pain in the ass. if (bitTest(listhandle->windowflags,UICLW_CanSelect)) { count = 0; pos = 0; if ( (listhandle->topitem != NULL) && (listhandle->UpperIndex < listhandle->ListTotal - listhandle->MaxIndex) ) { while ( (countMaxIndex) && (listhandle->UpperIndex < listhandle->ListTotal - listhandle->MaxIndex)) { if (listhandle->topitem->link.next!=NULL) { listhandle->topitem = listGetStructOfNode(listhandle->topitem->link.next); listhandle->UpperIndex++; uicListScrollBarAdjust(listhandle); } else break; count++; } uicListWindowCheckSel(listhandle); } if (listhandle->CurLineSelected!=NULL) { item = listGetStructOfNonPtrNode(listhandle->topitem->link); if (bitTest(item->flags,UICLI_CanSelect)) { bitClear(listhandle->CurLineSelected->flags,UICLI_Selected); listhandle->CurLineSelected = item; bitSet(listhandle->CurLineSelected->flags,UICLI_Selected); if (count < listhandle->MaxIndex) { if (count==0) { walk = listhandle->listofitems.tail; item = listGetStructOfNode(walk); while ((walk != NULL)&&(!bitTest(item->flags,UICLI_CanSelect))) { item = listGetStructOfNode(walk); walk = walk->prev; } if (bitTest(item->flags,UICLI_CanSelect)) { bitClear(listhandle->CurLineSelected->flags,UICLI_Selected); listhandle->CurLineSelected = item; bitSet(listhandle->CurLineSelected->flags,UICLI_Selected); } uicListWindowCheckSel(listhandle); return; } pos = uicListWindowRelativePos(listhandle) + count; if (pos > listhandle->MaxIndex-1) { pos = listhandle->MaxIndex-1; } } i=0; do { if (listhandle->CurLineSelected->link.next!=NULL) { bitClear(listhandle->CurLineSelected->flags,UICLI_Selected); listhandle->CurLineSelected = listGetStructOfNode(listhandle->CurLineSelected->link.next); bitSet(listhandle->CurLineSelected->flags,UICLI_Selected); } i++; } while (itopitem != NULL) && (listhandle->UpperIndex < listhandle->ListTotal - listhandle->MaxIndex) ) { count = 0; while ( (countMaxIndex) && (listhandle->UpperIndex < listhandle->ListTotal - listhandle->MaxIndex)) { if (listhandle->topitem->link.next!=NULL) { listhandle->topitem = listGetStructOfNode(listhandle->topitem->link.next); listhandle->UpperIndex++; uicListScrollBarAdjust(listhandle); } else break; count++; } } } } /*----------------------------------------------------------------------------- Name : uicListWindowProcess Description : processes list window events Inputs : standard region callbacks Outputs : Return : void ----------------------------------------------------------------------------*/ udword uicListWindowProcess(regionhandle region, sdword ID, udword event, udword data) { listwindowhandle listhandle; listitemhandle item; udword mask = 0; regionhandle tabRegion; listhandle = (listwindowhandle)region; if ((bitTest(listhandle->windowflags, UICLW_GetKeyPressed)) && (event == RPE_KeyDown) ) { listhandle->message = CM_KeyCaptured; listhandle->keypressed = data; feFunctionExecute(((featom *)region->atom)->name, region->atom, FALSE); bitClear(listhandle->windowflags, UICLW_GetKeyPressed); return(0); } switch (event) { case RPE_KeyDown: mask |= RPR_Redraw; /*#if ddunlop dbgMessagef("\nuicListWindowProcess: key pressed: 0x%x, '%c'", data, data); #endif*/ switch (data) { case ESCKEY: uicEscProcess(region,ID,event,data); break; case BACKSPACEKEY: break; case DELETEKEY: break; case ARRLEFT: case ARRUP: uicListWindowUpArrow(listhandle); item = listhandle->CurLineSelected; goto newSelection; break; case ARRRIGHT: case ARRDOWN: uicListWindowDownArrow(listhandle); item = listhandle->CurLineSelected; goto newSelection; break; case HOMEKEY: uicListWindowHome(listhandle); item = listhandle->CurLineSelected; goto newSelection; break; case ENDKEY: uicListWindowEnd(listhandle); item = listhandle->CurLineSelected; goto newSelection; break; case PAGEUPKEY: uicListWindowPageUp(listhandle); item = listhandle->CurLineSelected; goto newSelection; break; case PAGEDOWNKEY: uicListWindowPageDown(listhandle); item = listhandle->CurLineSelected; goto newSelection; break; case TABKEY: // process this tab key to go to the next tabstop tabRegion = regSiblingFindByFunction(region, uicTabProcess); if (tabRegion == NULL) break; uicTabProcess(region, tabRegion->userID, 0, 0); break; case SPACEKEY: case ENTERKEY: // pass the enter key press onto the listwindow callback listhandle->message = CM_AcceptText; feFunctionExecute(((featom *)region->atom)->name, region->atom, FALSE); break; /*#if ddunlop default: dbgMessagef(" (unprocessed)"); #endif*/ } break; case RPE_DoubleLeft: dbgMessage("\nDouble click"); if (listhandle->ListTotal==0) break; item = uicListGetItemClicked(listhandle, mouseCursorY()); if (item != NULL) { if (listhandle->CurLineSelected != NULL) { bitClear(listhandle->CurLineSelected->flags,UICLI_Selected); } listhandle->CurLineSelected = item; bitSet(item->flags,UICLI_Selected); // pass this onto the listwindow callback listhandle->message = CM_DoubleClick; feFunctionExecute(((featom *)region->atom)->name, region->atom, FALSE); } mask |= RPR_Redraw; break; case RPE_ReleaseLeft: if (mouseCursorY() < region->rect.y0+listhandle->TitleHeight) { if (listhandle->windowflags & UICLW_CanClickOnTitle) { dbgAssert(listhandle->titleprocess!=NULL); listhandle->titleprocess(region, mouseCursorX()); } } else { if (listhandle->ListTotal==0) break; item = uicListGetItemClicked(listhandle, mouseCursorY()); newSelection: if (item != NULL) { if (listhandle->CurLineSelected != NULL) { bitClear(listhandle->CurLineSelected->flags,UICLI_Selected); } listhandle->CurLineSelected = item; bitSet(item->flags,UICLI_Selected); // pass this onto the listwindow callback listhandle->message = CM_NewItemSelected; soundEvent(NULL, UI_Click); feFunctionExecute(((featom *)region->atom)->name, region->atom, FALSE); } } mask |= RPR_Redraw; break; case RPE_WheelUp: listhandle->processFunction(region,ID,event,data); mask |= RPR_Redraw; break; case RPE_WheelDown: listhandle->processFunction(region,ID,event,data); mask |= RPR_Redraw; break; case RPE_PressLeft: if ( (!bitTest(listhandle->reg.status, RSF_CurrentSelected)) && (bitTest(listhandle->windowflags,UICLW_CanHaveFocus))) { uicClearCurrent(region); uicSetCurrent(region, FALSE); // soundEvent(NULL, UI_Click); mask |= RPR_Redraw; } break; case RPE_EnterHoldLeft: // mask |= RPR_Redraw; break; case RPE_HoldLeft: // mask |= RPR_Redraw; break; } if (mask != 0) { regRecursiveSetDirty(region); } return mask; } /*----------------------------------------------------------------------------- Name : uicRadioButtonDraw Description : Draw a radioButton Inputs : reg - region representing toggle Outputs : Return : ----------------------------------------------------------------------------*/ void uicRadioButtonDraw(regionhandle reg) { /* rectangle erase; erase = reg->rect; //erase the background to get rid of text that might be there erase.y0 += 3; erase.x0 += 3; erase.x1 -= 3; */ //primRectSolid2(&erase, colBlack); if (feStack[feStackIndex].screen != ((buttonhandle)reg)->screen) { if (FECHECKED(((featom *)reg->userID))) ferDrawRadioButton(reg->rect, r_on); else ferDrawRadioButton(reg->rect, r_off); return; } if (!uicMouseFocus) uicFocusToMouse(reg); if (bitTest(reg->status, RSF_RegionDisabled)) { if (FECHECKED(((featom *)reg->userID))) ferDrawRadioButton(reg->rect, r_on_disabled); else ferDrawRadioButton(reg->rect, r_off_disabled); } else { if (FECHECKED(((featom *)reg->userID))) { if (bitTest(reg->status, RSF_LeftPressed)) { if (bitTest(reg->status, RSF_MouseInside)) { ferDrawRadioButton(reg->rect, r_on_focus_mouse); } else { ferDrawRadioButton(reg->rect, r_on_focus); } } else if (bitTest(reg->status, RSF_CurrentSelected)) { if (bitTest(reg->status, RSF_MouseInside)) { ferDrawRadioButton(reg->rect, r_on_focus_mouse); } else { ferDrawRadioButton(reg->rect, r_on_focus); } } else if (bitTest(reg->status, RSF_MouseInside)) { ferDrawRadioButton(reg->rect, r_on_mouse); } else { ferDrawRadioButton(reg->rect, r_on); } } else { if (bitTest(reg->status, RSF_LeftPressed)) { if (bitTest(reg->status, RSF_MouseInside)) { ferDrawRadioButton(reg->rect, r_off_focus_mouse); } else { ferDrawRadioButton(reg->rect, r_off_focus); } } else if (bitTest(reg->status, RSF_CurrentSelected)) { if (bitTest(reg->status, RSF_MouseInside)) { ferDrawRadioButton(reg->rect, r_off_focus_mouse); } else { ferDrawRadioButton(reg->rect, r_off_focus); } } else if (bitTest(reg->status, RSF_MouseInside)) { ferDrawRadioButton(reg->rect, r_off_mouse); } else { ferDrawRadioButton(reg->rect, r_off); } } } } /*----------------------------------------------------------------------------- Name : uicBitmapButtonDraw Description : Draw a checkBox Inputs : reg - region representing toggle Outputs : Return : ----------------------------------------------------------------------------*/ void uicBitmapButtonDraw(regionhandle reg) { if (feStack[feStackIndex].screen != ((buttonhandle)reg)->screen) { if (FECHECKED(((featom *)reg->userID))) ferDrawRadioButton(reg->rect, r_on); else ferDrawRadioButton(reg->rect, r_off); return; } if (!uicMouseFocus) uicFocusToMouse(reg); if (FECHECKED(((featom *)reg->userID))) { if (bitTest(reg->status, RSF_MouseInside)) { ferDrawBitmapButton(reg, bb_on_mouse); } else { ferDrawBitmapButton(reg, bb_on); } } else { if (bitTest(reg->status, RSF_MouseInside)) { ferDrawBitmapButton(reg, bb_off_mouse); } else { ferDrawBitmapButton(reg, bb_off); } } } /*----------------------------------------------------------------------------- Name : uicCheckBoxDraw Description : Draw a checkBox Inputs : reg - region representing toggle Outputs : Return : ----------------------------------------------------------------------------*/ void uicCheckBoxDraw(regionhandle reg) { /* rectangle erase; erase = reg->rect; //erase the background to get rid of text that might be there erase.y0 += 3; erase.x0 += 3; erase.x1 -= 3; */ //primRectSolid2(&erase, colBlack); if (feStack[feStackIndex].screen != ((buttonhandle)reg)->screen) { if (FECHECKED(((featom *)reg->userID))) ferDrawCheckbox(reg->rect, c_on_disabled); else ferDrawCheckbox(reg->rect, c_off_disabled); return; } if (!uicMouseFocus) uicFocusToMouse(reg); if (bitTest(reg->status, RSF_RegionDisabled)) { if (FECHECKED(((featom *)reg->userID))) ferDrawCheckbox(reg->rect, c_on_disabled); else ferDrawCheckbox(reg->rect, c_off_disabled); } else { if (FECHECKED(((featom *)reg->userID))) { if (bitTest(reg->status, RSF_LeftPressed)) { if (bitTest(reg->status, RSF_MouseInside)) { ferDrawCheckbox(reg->rect, c_on_focus_mouse); } else { ferDrawCheckbox(reg->rect, c_on_focus); } } else if (bitTest(reg->status, RSF_CurrentSelected)) { if (bitTest(reg->status, RSF_MouseInside)) { ferDrawCheckbox(reg->rect, c_on_focus_mouse); } else { ferDrawCheckbox(reg->rect, c_on_focus); } } else if (bitTest(reg->status, RSF_MouseInside)) { ferDrawCheckbox(reg->rect, c_on_mouse); } else { ferDrawCheckbox(reg->rect, c_on); } } else { if (bitTest(reg->status, RSF_LeftPressed)) { if (bitTest(reg->status, RSF_MouseInside)) { ferDrawCheckbox(reg->rect, c_off_focus_mouse); } else { ferDrawCheckbox(reg->rect, c_off_focus); } } else if (bitTest(reg->status, RSF_CurrentSelected)) { if (bitTest(reg->status, RSF_MouseInside)) { ferDrawCheckbox(reg->rect, c_off_focus_mouse); } else { ferDrawCheckbox(reg->rect, c_off_focus); } } else if (bitTest(reg->status, RSF_MouseInside)) { ferDrawCheckbox(reg->rect, c_off_mouse); } else { ferDrawCheckbox(reg->rect, c_off); } } } } void Approach(approacher *app) { real32 decelgoal,deceltime; app->currentvalue += app->vel; if (app->vel > 0.0f) { deceltime = app->vel / app->acc; decelgoal = app->currentvalue + 0.5f*app->acc*app->currentvalue*app->currentvalue; if (decelgoal > app->target) { app->vel = app->vel - app->acc; } else { if (((app->currentvalue - app->target)/(decelgoal - app->target)) > app->threshold) app->vel = app->vel + app->acc; else ; //don't change vel; } } else { deceltime = -app->vel / app->acc; decelgoal = app->currentvalue - 0.5f*app->acc*app->currentvalue*app->currentvalue; if (decelgoal > app->target) { if (((app->currentvalue - app->target)/(decelgoal - app->target)) > app->threshold) app->vel = app->vel - app->acc; else ; //don't change vel; } else { app->vel = app->vel + app->acc; } } } void SetHSliderValue(sliderhandle shandle) { real32 val; val = (real32)(mouseCursorX() - shandle->reg.rect.x0); val = shandle->maxvalue * val / (real32)(shandle->reg.rect.x1-shandle->reg.rect.x0); shandle->value = (udword)val; } void SetVSliderValue(sliderhandle shandle) { real32 val; val = (real32)(mouseCursorY() - shandle->reg.rect.y0); val = shandle->maxvalue * val / (real32)(shandle->reg.rect.y1-shandle->reg.rect.y0); shandle->value = (udword)val; } /*----------------------------------------------------------------------------- Name : uicHorizSliderProcess Description : Draw a checkBox Inputs : reg - region representing toggle Outputs : Return : ----------------------------------------------------------------------------*/ udword uicHorizSliderProcess(regionhandle region, sdword ID, udword event, udword data) { sliderhandle shandle; udword mask = 0; //x,y; shandle = (sliderhandle)region; switch (event) { case RPE_ReleaseLeft: //shandle->processFunction(region, ID, CM_ButtonClick, shandle->clickType); mouseClipToRect(NULL); mask |= RPR_Redraw; break; case RPE_PressLeft: mouseClipToRect(®ion->rect); SetHSliderValue(shandle); mask |= RPR_Redraw; if (shandle->processFunction) shandle->processFunction(region,ID,event,data); break; case RPE_EnterHoldLeft: //shandle->clickType = SC_Thumb; mask |= RPR_Redraw; break; case RPE_HoldLeft: SetHSliderValue(shandle); if (shandle->processFunction) shandle->processFunction(region,ID,event,data); mask |= RPR_Redraw; break; case RPE_Enter: case RPE_Exit: case RPE_ExitHoldLeft: mask |= RPR_Redraw; break; #if 0 default: shandle->clickType = SC_NoRegion; #endif } if (mask != 0) { regRecursiveSetDirty(region); } return mask; } udword uicVertSliderProcess(regionhandle region, sdword ID, udword event, udword data) { sliderhandle shandle; udword mask = 0; //x,y; shandle = (sliderhandle)region; switch (event) { case RPE_ReleaseLeft: //shandle->processFunction(region, ID, CM_ButtonClick, shandle->clickType); mouseClipToRect(NULL); mask |= RPR_Redraw; break; case RPE_WheelUp: //shandle->processFunction(region, ID, CM_ButtonClick, SC_Negative); mask |= RPR_Redraw; break; case RPE_WheelDown: //shandle->processFunction(region, ID, CM_ButtonClick, SC_Positive); mask |= RPR_Redraw; break; case RPE_PressLeft: mouseClipToRect(®ion->rect); SetVSliderValue(shandle); mask |= RPR_Redraw; if (shandle->processFunction) shandle->processFunction(region,ID,event,data); break; case RPE_EnterHoldLeft: //shandle->clickType = SC_Thumb; mask |= RPR_Redraw; break; case RPE_HoldLeft: SetVSliderValue(shandle); if (shandle->processFunction) shandle->processFunction(region,ID,event,data); mask |= RPR_Redraw; break; case RPE_Enter: case RPE_Exit: case RPE_ExitHoldLeft: mask |= RPR_Redraw; break; #if 0 default: shandle->clickType = SC_NoRegion; #endif } if (mask != 0) { regRecursiveSetDirty(region); } return mask; } /*----------------------------------------------------------------------------- Name : uicHorizSliderDraw Description : Draw a checkBox Inputs : reg - region representing slider Outputs : Return : ----------------------------------------------------------------------------*/ void uicHorizSliderDraw(regionhandle reg) { /* rectangle erase; erase = reg->rect; //erase the background to get rid of text that might be there erase.y0 += 3; erase.x0 += 3; erase.x1 -= 3; */ if (bitTest(reg->status, RSF_RegionDisabled)) { ferDrawHorizSlider((sliderhandle)reg, s_disabled); } else if (bitTest(reg->status, RSF_MouseInside)) { if (bitTest(reg->status, RSF_LeftPressed)) { ferDrawHorizSlider((sliderhandle)reg, s_on_mouse); } else { ferDrawHorizSlider((sliderhandle)reg, s_off_mouse); } } else { ferDrawHorizSlider((sliderhandle)reg, s_off); } } void uicVertSliderDraw(regionhandle reg) { if (bitTest(reg->status, RSF_MouseInside)) { if (bitTest(reg->status, RSF_LeftPressed)) { ferDrawVertSlider((sliderhandle)reg, s_on_mouse); } else { ferDrawVertSlider((sliderhandle)reg, s_off_mouse); } } else { ferDrawVertSlider((sliderhandle)reg, s_off); } } /*----------------------------------------------------------------------------- Name : uicRepositionText Description : Reposition the text of a text entry control such that the cursor is still on-screen. Inputs : entry - entry to reposition. jump - if TRUE and the cursor is out of the window, the text will be repositioned more than enough to get the cursor back into the window. It will be jumped so to speak. Outputs : Return : TRUE if cursor needed repositioning. ----------------------------------------------------------------------------*/ bool uicRepositionText(textentryhandle entry, bool jumpReposition) { sdword length; fonthandle fhSave; fhSave = fontCurrentGet(); //save the current font fontMakeCurrent(entry->currentFont); //select the appropriate font if (entry->iCharacter < entry->iVisible) { //if cursor off right of window entry->iVisible = entry->iCharacter; return(TRUE); } length = fontWidthN(entry->textBuffer + entry->iVisible, entry->iCharacter - entry->iVisible); if (length > entry->textRect.x1 - entry->textRect.x0) { //if cursor off right of window do { entry->iVisible++; length = fontWidthN(entry->textBuffer + entry->iVisible, entry->iCharacter - entry->iVisible); dbgAssert(entry->iVisible <= entry->iCharacter); } while (length > entry->textRect.x1 - entry->textRect.x0); return(TRUE); } fontMakeCurrent(fhSave); return(FALSE); } /*----------------------------------------------------------------------------- Name : uicInsertCharacter Description : Insert a typed character into the text box. Inputs : entry - text entry control to insert the character into. character - character to insert Outputs : inserts the character at the current point of typing. Return : TRUE if the character was inserted correctly. ----------------------------------------------------------------------------*/ bool uicInsertCharacter(textentryhandle entry, udword character) { sdword index; regVerify(&entry->reg); if (bitTest(entry->textflags, UICTE_FileName)) { //if it's a filename we're typing if (strchr(UICTE_FileNameInvalids, character)) { //and it's an invalid filename character return(FALSE); } } if (strlen(entry->textBuffer)+1 >= entry->bufferLength - 1) { return(FALSE); } //insert an empty space for the character for (index = strlen(entry->textBuffer); index >= entry->iCharacter; index--) { entry->textBuffer[index + 1] = entry->textBuffer[index]; } entry->textBuffer[entry->iCharacter] = (ubyte)character;//put in the new character entry->iCharacter++; //move the cursor over a bit dbgAssert(strlen(entry->textBuffer) < entry->bufferLength);//make sure we didn't run on too long uicRepositionText(entry, FALSE); //reposition the text return(TRUE); } /*----------------------------------------------------------------------------- Name : uicBackspaceCharacter Description : Delete the character to the left of the cursor in a text entry box. Inputs : entry - control to delete a character from Outputs : Return : TRUE if the character was deleted properly ----------------------------------------------------------------------------*/ bool uicBackspaceCharacter(textentryhandle entry) { sdword index; regVerify(&entry->reg); if (entry->iCharacter == 0) { //if there is nothing to the left of the cursor return(FALSE); //nothing to do } for (index = entry->iCharacter; index <= strlen(entry->textBuffer); index++) { entry->textBuffer[index - 1] = entry->textBuffer[index]; } entry->iCharacter--; uicRepositionText(entry, TRUE); //reposition the text return(TRUE); } /*----------------------------------------------------------------------------- Name : uicDeleteCharacter Description : Delete the character to the right of the cursor. Inputs : entry - control to delete character from Outputs : Return : TRUE if the character was deleted properly ----------------------------------------------------------------------------*/ bool uicDeleteCharacter(textentryhandle entry) { sdword index; regVerify(&entry->reg); if (entry->iCharacter == strlen(entry->textBuffer)) { //if nothing to right of cursor return(FALSE); } for (index = entry->iCharacter; index <= strlen(entry->textBuffer); index++) { entry->textBuffer[index] = entry->textBuffer[index + 1]; } return(TRUE); } /*----------------------------------------------------------------------------- Name : uicCursorMoveRelative Description : Move the cursor in a text entry box. Inputs : entry - entry who's cursor we are to move amount - amount to move the cursor by. Can be negative. Outputs : Return : actual amount the cursor was moved ----------------------------------------------------------------------------*/ sdword uicCursorMoveRelative(textentryhandle entry, sdword amount) { sdword oldICharacter; regVerify(&entry->reg); oldICharacter = entry->iCharacter; entry->iCharacter += amount; if (entry->iCharacter < 0) { entry->iCharacter = 0; } if (entry->iCharacter > strlen(entry->textBuffer)) { entry->iCharacter = strlen(entry->textBuffer); } uicRepositionText(entry, TRUE); //reposition the text return(oldICharacter - entry->iCharacter); } /*----------------------------------------------------------------------------- Name : uicCursorWordLeft Description : Move the cursor to the left one word. Inputs : Outputs : Return : TRUE if the cursor was moved. ----------------------------------------------------------------------------*/ bool uicCursorWordLeft(textentryhandle entry) { if (entry->iCharacter == 0) { //if can't move left return(FALSE); } //look left until we find a non-blank character while (entry->iCharacter > 0) { entry->iCharacter--; if (!strchr(uicSpaceCharacters, entry->textBuffer[entry->iCharacter])) { break; } } //try to find a blank character while (entry->iCharacter > 0) { if (strchr(uicSpaceCharacters, entry->textBuffer[entry->iCharacter - 1])) { break; } entry->iCharacter--; } uicRepositionText(entry, TRUE); //reposition the text return(TRUE); } /*----------------------------------------------------------------------------- Name : uicCursorWordRight Description : Move the cursor to the left one word. Inputs : Outputs : Return : TRUE if the cursor was moved. ----------------------------------------------------------------------------*/ bool uicCursorWordRight(textentryhandle entry) { sdword length = strlen(entry->textBuffer); if (entry->iCharacter >= length - 1) { //if can't move right return(FALSE); } //look right until we find a non-blank character while (entry->iCharacter < length) { if (!strchr(uicSpaceCharacters, entry->textBuffer[entry->iCharacter])) { break; } entry->iCharacter++; } //try to find a blank character while (entry->iCharacter < length) { if (strchr(uicSpaceCharacters, entry->textBuffer[entry->iCharacter])) { break; } entry->iCharacter++; } uicRepositionText(entry, TRUE); //reposition the text return(TRUE); } udword keyLanguageTranslate(udword wParam); /*----------------------------------------------------------------------------- Name : uicTextEntryProcess Description : Process messages for a text entry box. Inputs : data - keystroke scancode with shift status Outputs : Return : ----------------------------------------------------------------------------*/ udword uicTextEntryProcess(regionhandle reg, sdword ID, udword event, udword data) { textentryhandle entry = (textentryhandle)reg; featom *atom = (featom *)reg->userID; regionhandle tabRegion; udword mask = 0; bool bShift = bitTest(data, RF_ShiftBit); bitClear(data, RF_ShiftBit); switch(event) { case RPE_KeyDown: mask |= RPR_Redraw; #if UIC_VERBOSE_LEVEL >= 2 dbgMessagef("\nuicTextEntryProcess: key pressed: 0x%x, '%c'", data, data); #endif //data = keyLanguageTranslate(data); switch (data) { case ESCKEY: entry->message = CM_RejectText; feFunctionExecute(atom->name, atom, FALSE); uicEscProcess(reg,ID,event,data); break; case ENTERKEY: entry->message = CM_AcceptText; feFunctionExecute(atom->name, atom, FALSE); if (!(entry->textflags&UICTE_NoLossOfFocus)) { bitClear(reg->status, RSF_KeyCapture); regKeysFocussed = FALSE; } break; case BACKSPACEKEY: uicBackspaceCharacter(entry); break; case DELETEKEY: uicDeleteCharacter(entry); break; case ARRLEFT: if (keyIsHit(CONTROLKEY)) { uicCursorWordLeft(entry); } else { uicCursorMoveRelative(entry, -1); } break; case ARRRIGHT: if (keyIsHit(CONTROLKEY)) { uicCursorWordRight(entry); } else { uicCursorMoveRelative(entry, 1); } break; case HOMEKEY: uicCursorMoveRelative(entry, SWORD_Min); break; case ENDKEY: uicCursorMoveRelative(entry, SWORD_Max); break; case TABKEY: tabRegion = regSiblingFindByFunction(reg, uicTabProcess); if (tabRegion == NULL) break; uicTabProcess(reg, tabRegion->userID, 0, 0); break; case PAGEUPKEY: case PAGEDOWNKEY: if (bitTest(entry->textflags,UICTE_SpecialChars)) { entry->message = CM_SpecialKey; entry->key = data; feFunctionExecute(atom->name, atom, FALSE); } break; default: switch (strCurKeyboardLanguage) { case languageEnglish: if (bitTest(entry->textflags,UICTE_NumberEntry)) { if ( (data>= ZEROKEY) && (data<=NINEKEY) ) { uicInsertCharacter(entry, uicKeyEntryTable[data].regularKey); } if ( (data>=NUMPAD0) && (data<=NUMPAD9) ) { uicInsertCharacter(entry, uicKeyEntryTable[data].regularKey); } } else { if (bShift) { if (uicKeyEntryTable[data].shiftKey) { if ( (bitTest(entry->textflags, UICTE_UserNameEntry)) && (data != SPACEKEY) ) { uicInsertCharacter(entry, uicKeyEntryTable[data].shiftKey); } else uicInsertCharacter(entry, uicKeyEntryTable[data].shiftKey); } } else if (uicKeyEntryTable[data].regularKey) { if (bitTest(entry->textflags, UICTE_UserNameEntry)) { if (data != SPACEKEY) uicInsertCharacter(entry, uicKeyEntryTable[data].regularKey); } else uicInsertCharacter(entry, uicKeyEntryTable[data].regularKey); } } if (bitTest(entry->textflags, UICTE_ChatTextEntry)) { entry->message = CM_KeyPressed; feFunctionExecute(atom->name, atom, FALSE); } #if UIC_VERBOSE_LEVEL >= 2 dbgMessagef(" (unprocessed)"); #endif break; case languageFrench: if (bitTest(entry->textflags,UICTE_NumberEntry)) { if ( (data>= ZEROKEY) && (data<=NINEKEY) ) { uicInsertCharacter(entry, uicFrenchKeyEntryTable[data].regularKey); } if ( (data>=NUMPAD0) && (data<=NUMPAD9) ) { uicInsertCharacter(entry, uicFrenchKeyEntryTable[data].regularKey); } } else { if (bShift) { if (uicFrenchKeyEntryTable[data].shiftKey) { if ( (bitTest(entry->textflags, UICTE_UserNameEntry)) && (data != SPACEKEY) ) { uicInsertCharacter(entry, uicFrenchKeyEntryTable[data].shiftKey); } else uicInsertCharacter(entry, uicFrenchKeyEntryTable[data].shiftKey); } } else if (uicFrenchKeyEntryTable[data].regularKey) { if (bitTest(entry->textflags, UICTE_UserNameEntry)) { if (data != SPACEKEY) uicInsertCharacter(entry, uicFrenchKeyEntryTable[data].regularKey); } else uicInsertCharacter(entry, uicFrenchKeyEntryTable[data].regularKey); } } if (bitTest(entry->textflags, UICTE_ChatTextEntry)) { entry->message = CM_KeyPressed; feFunctionExecute(atom->name, atom, FALSE); } #if UIC_VERBOSE_LEVEL >= 2 dbgMessagef(" (unprocessed)"); #endif break; case languageGerman: if (bitTest(entry->textflags,UICTE_NumberEntry)) { if ( (data>= ZEROKEY) && (data<=NINEKEY) ) { uicInsertCharacter(entry, uicGermanKeyEntryTable[data].regularKey); } if ( (data>=NUMPAD0) && (data<=NUMPAD9) ) { uicInsertCharacter(entry, uicGermanKeyEntryTable[data].regularKey); } } else { if (bShift) { if (uicGermanKeyEntryTable[data].shiftKey) { if ( (bitTest(entry->textflags, UICTE_UserNameEntry)) && (data != SPACEKEY) ) { uicInsertCharacter(entry, uicGermanKeyEntryTable[data].shiftKey); } else uicInsertCharacter(entry, uicGermanKeyEntryTable[data].shiftKey); } } else if (uicGermanKeyEntryTable[data].regularKey) { if (bitTest(entry->textflags, UICTE_UserNameEntry)) { if (data != SPACEKEY) uicInsertCharacter(entry, uicGermanKeyEntryTable[data].regularKey); } else uicInsertCharacter(entry, uicGermanKeyEntryTable[data].regularKey); } } if (bitTest(entry->textflags, UICTE_ChatTextEntry)) { entry->message = CM_KeyPressed; feFunctionExecute(atom->name, atom, FALSE); } #if UIC_VERBOSE_LEVEL >= 2 dbgMessagef(" (unprocessed)"); #endif break; case languageSpanish: if (bitTest(entry->textflags,UICTE_NumberEntry)) { if ( (data>= ZEROKEY) && (data<=NINEKEY) ) { uicInsertCharacter(entry, uicSpanishKeyEntryTable[data].regularKey); } if ( (data>=NUMPAD0) && (data<=NUMPAD9) ) { uicInsertCharacter(entry, uicSpanishKeyEntryTable[data].regularKey); } } else { if (bShift) { if (uicSpanishKeyEntryTable[data].shiftKey) { if ( (bitTest(entry->textflags, UICTE_UserNameEntry)) && (data != SPACEKEY) ) { uicInsertCharacter(entry, uicSpanishKeyEntryTable[data].shiftKey); } else uicInsertCharacter(entry, uicSpanishKeyEntryTable[data].shiftKey); } } else if (uicSpanishKeyEntryTable[data].regularKey) { if (bitTest(entry->textflags, UICTE_UserNameEntry)) { if (data != SPACEKEY) uicInsertCharacter(entry, uicSpanishKeyEntryTable[data].regularKey); } else uicInsertCharacter(entry, uicSpanishKeyEntryTable[data].regularKey); } } if (bitTest(entry->textflags, UICTE_ChatTextEntry)) { entry->message = CM_KeyPressed; feFunctionExecute(atom->name, atom, FALSE); } #if UIC_VERBOSE_LEVEL >= 2 dbgMessagef(" (unprocessed)"); #endif break; case languageItalian: if (bitTest(entry->textflags,UICTE_NumberEntry)) { if ( (data>= ZEROKEY) && (data<=NINEKEY) ) { uicInsertCharacter(entry, uicItalianKeyEntryTable[data].regularKey); } if ( (data>=NUMPAD0) && (data<=NUMPAD9) ) { uicInsertCharacter(entry, uicItalianKeyEntryTable[data].regularKey); } } else { if (bShift) { if (uicItalianKeyEntryTable[data].shiftKey) { if ( (bitTest(entry->textflags, UICTE_UserNameEntry)) && (data != SPACEKEY) ) { uicInsertCharacter(entry, uicItalianKeyEntryTable[data].shiftKey); } else uicInsertCharacter(entry, uicItalianKeyEntryTable[data].shiftKey); } } else if (uicItalianKeyEntryTable[data].regularKey) { if (bitTest(entry->textflags, UICTE_UserNameEntry)) { if (data != SPACEKEY) uicInsertCharacter(entry, uicItalianKeyEntryTable[data].regularKey); } else uicInsertCharacter(entry, uicItalianKeyEntryTable[data].regularKey); } } if (bitTest(entry->textflags, UICTE_ChatTextEntry)) { entry->message = CM_KeyPressed; feFunctionExecute(atom->name, atom, FALSE); } #if UIC_VERBOSE_LEVEL >= 2 dbgMessagef(" (unprocessed)"); #endif break; } } break; case RPE_PressLeft: uicClearCurrent(reg); uicSetCurrent(reg, FALSE); entry->message = CM_GainFocus; feFunctionExecute(atom->name, atom, FALSE); soundEvent(NULL, UI_Click); mask |= RPR_Redraw; break; case RPE_ExitHoldLeft: case RPE_Enter: case RPE_Exit: mask |= RPR_Redraw; break; case RPE_ReleaseLeft: mask |= RPR_Redraw; break; default:; #if UIC_VERBOSE_LEVEL >= 1 dbgMessagef("\nuicTextEntryProcess: unimplemented or unsupported message: 0x%x, userID 0x%x, data 0x%x (%d)", event, ID, data, data); #endif } if (mask != 0) { regRecursiveSetDirty(reg); } return mask; } /*----------------------------------------------------------------------------- Name : uicTextEntryDraw Description : Draw a text entry region. Inputs : reg - region the text entry box corresponds to. Outputs : Return : ----------------------------------------------------------------------------*/ void uicTextEntryDraw(regionhandle reg) { featom *atom = (featom *)reg->userID; textentryhandle entry = (textentryhandle)reg; fonthandle fhSave; sdword caretLocation, nCharacters, length; sdword i, y; // udword timerInt, flashRateInt; char temp[256]; // text entry draw start *** if (!bitTest(entry->textflags,UICTE_NoTextures)) { if (feStack[feStackIndex].screen != ((buttonhandle)reg)->screen) { ferDrawButton(reg->rect, te_off); } else { if (!uicMouseFocus) uicFocusToMouse(reg); if (bitTest(reg->status, RSF_RegionDisabled)) { ferDrawButton(reg->rect, te_off_disabled); } else if (bitTest(reg->status, RSF_LeftPressed)) { if (bitTest(reg->status, RSF_MouseInside)) { ferDrawButton(reg->rect, te_on_focus_mouse); } else { ferDrawButton(reg->rect, te_off_focus_mouse); } } else if (bitTest(reg->status, RSF_CurrentSelected)) { if (bitTest(reg->status, RSF_MouseInside)) { ferDrawButton(reg->rect, te_off_focus_mouse); } else { ferDrawButton(reg->rect, te_off_focus); } } else if (bitTest(reg->status, RSF_MouseInside)) { ferDrawButton(reg->rect, te_off_mouse); } else { ferDrawButton(reg->rect, te_off); } } } // text entry draw end *** dbgAssert(entry->textBuffer != NULL); //make sure there is a string fhSave = fontCurrentGet(); //save the current font fontMakeCurrent(entry->currentFont); //select the appropriate font if (bitTest(entry->textflags, UICTE_DropShadow)) { fontShadowSet(FS_SE, entry->shadowColor); } y = ((entry->textRect.y1 - entry->textRect.y0) - fontHeight(" ")) / 2 + entry->textRect.y0; if (strlen(entry->textBuffer) != 0) { //if there is a string to draw //figure how many characters to draw nCharacters = strlen(entry->textBuffer + entry->iVisible); length = fontWidth(entry->textBuffer + entry->iVisible); while (nCharacters > 0 && length > entry->textRect.x1 - entry->textRect.x0) { length = fontWidthN(entry->textBuffer + entry->iVisible, nCharacters); nCharacters--; } if (entry->textflags&UICTE_PasswordEntry) { memset(temp,0,256); for (i=0;itextRect.x0, y, entry->borderColor, temp, nCharacters); } else { fontPrintN(entry->textRect.x0, y, entry->borderColor, entry->textBuffer + entry->iVisible, nCharacters); } } //now draw a flashing caret, if there is input focus if (bitTest(reg->status, RSF_KeyCapture)) { //if this region has input focus //timerInt = (udword)(taskTimeElapsed * 256); //flashRateInt = (udword)(entry->flashRate * 256); // if ((timerInt % flashRateInt) > (flashRateInt / 2)) // { //if the flash action in is the 'on' state if (entry->textflags&UICTE_PasswordEntry) { caretLocation = entry->textRect.x0 + fontWidthN(temp, entry->iCharacter - entry->iVisible); } else { caretLocation = entry->textRect.x0 + fontWidthN(entry->textBuffer + entry->iVisible, entry->iCharacter - entry->iVisible); } /* if (frFontRegistry[entry->currentFont].fontdat->character['|'] != NULL) { //draw a pipe of the current font if there is one fontPrint(caretLocation, y, entry->borderColor, "|"); } else*/ { //draw a small rectangle instead of a pipe primLine2(caretLocation-1, y+2, caretLocation-1, y + fontHeight(" "), entry->borderColor); } // } } fontShadowSet(FS_NONE, colBlack); fontMakeCurrent(fhSave); } /*----------------------------------------------------------------------------- Name : uicDragButtonProcess Description : Process a drag button Inputs : Outputs : Return : ----------------------------------------------------------------------------*/ udword uicDragButtonProcess(regionhandle region, sdword ID, udword event, udword data) { udword mask = 0; switch (event) { case RPE_PressLeft: uicClearCurrent(region); uicSetCurrent(region, FALSE); soundEvent(NULL, UI_Click); mask |= RPR_Redraw; ((buttonhandle)region)->clickX = mouseCursorX();//record where the user clicked ((buttonhandle)region)->clickY = mouseCursorY(); mouseCursorHide(); ((buttonhandle)region)->bDragged = FALSE; break; case RPE_KeyDown: soundEvent(NULL, UI_Click); ((buttonhandle)region)->processFunction(region, ID, CM_ButtonClick, 0); ((buttonhandle)region)->bDragged = FALSE; break; case RPE_ReleaseLeft: mouseCursorShow(); //...see if there was draggage if (!((buttonhandle)region)->bDragged) { //if the mouse was never dragged uicDragX = uicDragY = 0; ((buttonhandle)region)->processFunction(region, ID, CM_ButtonClick, 0); } break; case RPE_ExitHoldLeft: bitSet(region->status, RSF_MouseInside); //make mouse think it's still in this region bitSet(region->status, RSF_LeftPressed); //fall through case RPE_HoldLeft: case RPE_EnterHoldLeft: if (((buttonhandle)region)->bDragged) { //if dragging has already happened if (((buttonhandle)region)->clickX != mouseCursorX() || ((buttonhandle)region)->clickY != mouseCursorY()) { //if the mouse has been dragged //...register the motion uicDragX = mouseCursorX() - ((buttonhandle)region)->clickX; uicDragY = mouseCursorY() - ((buttonhandle)region)->clickY; ((buttonhandle)region)->processFunction(region, ID, CM_ButtonDrag, ((((buttonhandle)region)->clickY - mouseCursorY()) << 16) + (((buttonhandle)region)->clickX - mouseCursorX())); //...reset the mouse cursor mousePositionSet(((buttonhandle)region)->clickX, ((buttonhandle)region)->clickY); } } else { //no dragging yet if (abs(((buttonhandle)region)->clickX - mouseCursorX()) >= UIC_DragButtonThresholdX || abs(((buttonhandle)region)->clickY - mouseCursorY()) >= UIC_DragButtonThresholdY) { //if the mouse has been dragged far enough to be considered a drag //...register the motion ((buttonhandle)region)->bDragged = TRUE; //because the drag data has to go through several layers of //calling and I don't want to retrofit any of these API's, //let's just pass it in global variables. uicDragX = mouseCursorX() - ((buttonhandle)region)->clickX; uicDragY = mouseCursorY() - ((buttonhandle)region)->clickY; ((buttonhandle)region)->processFunction(region, ID, CM_ButtonDrag, 0); //...reset the mouse cursor/region status to make everybody think we're still inside the region // regClickedLeft = region; //no has mouse press focus mousePositionSet(((buttonhandle)region)->clickX, ((buttonhandle)region)->clickY); } } break; case RPE_Enter: case RPE_Exit: if (!mouseLeftButton()) { //if mouse button was released outside of region mouseCursorShow(); } mask |= RPR_Redraw; break; } if (mask != 0) { regRecursiveSetDirty(region); } return(mask); } /*============================================================================= Functions: =============================================================================*/ //startup/shutdown /*----------------------------------------------------------------------------- Name : uicStartup/uicShudown Description : Startup/shutdown of module Inputs : void Outputs : Return : void ----------------------------------------------------------------------------*/ void uicStartup(void) { ; #if UIC_TEST uicChildButtonAlloc((controlhandle)ghMainRegion, 10, 10, 10, 100, 20, uicTestProcess, 0); #endif } void uicShutdown(void) { ; } /*----------------------------------------------------------------------------- Name : uicChildButtonAlloc Description : Create a button which is a child of either a region or another control This is used for creating regular buttons, toggle buttons, check boxes and radio buttons Inputs : parent - handle to the parent region or control ID - control ID of the button to be created x, y, width, height - position and size of the control function - function to recieve notification of button presses flags - flags for control and the type of control (see above list) Outputs : allocates and initializes the region Return : handle to the newly created button ----------------------------------------------------------------------------*/ buttonhandle uicChildButtonAlloc(controlhandle parent, sdword ID, sdword x, sdword y, sdword width, sdword height, uicfunction function, udword flags) { buttonhandle newHandle; featom *atom=(featom *)ID; newHandle = (buttonhandle)regChildAlloc((regionhandle)parent, ID, //create region with some extra RAM x, y, width, height, uicStructureExtra(uicbutton), uicControlFunctions[flags & CFM_ControlType].regionFilter); if (bitTest(atom->flags,FAF_Disabled)) bitSet(newHandle->reg.status,RSF_RegionDisabled); dbgAssert(uicControlFunctions[flags & CFM_ControlType].function != NULL); dbgAssert(uicControlFunctions[flags & CFM_ControlType].drawFunction != NULL); regFunctionSet((regionhandle)newHandle, //set process/draw functions uicControlFunctions[flags & CFM_ControlType].function); if (bitTest(atom->flags, FAF_Hidden)) { regDrawFunctionSet((regionhandle)newHandle, NULL); } else { regDrawFunctionSet((regionhandle)newHandle, uicControlFunctions[flags & CFM_ControlType].drawFunction); } newHandle->processFunction = function; //store function pointer newHandle->clickX = mouseCursorX(); //record where the user clicked newHandle->clickY = mouseCursorY(); // newHandle->regionFilter = 0; //default to no region messages passed through return(newHandle); } /* * convenient */ void setRect(rectangle *rect, rectangle* ofs, uword x0, uword x1, uword y0, uword y1) { rect->x0 = ofs->x0 + x0; rect->y0 = ofs->y0 + y0; rect->x1 = ofs->x0 + x1; rect->y1 = ofs->y0 + y1; } /*----------------------------------------------------------------------------- Name : uicChildScrollBarAlloc Description : Create a scrollbar which is a child of either a region or another control Inputs : parent - handle to the parent region or control ID - control ID of the button to be created x,y, width, height - position and size of the control function - function to recieve notification of button presses flags - flags for control and the type of control (see above list) Outputs : allocates and initializes the region Return : handle to the newly created scrollbar ----------------------------------------------------------------------------*/ scrollbarhandle uicChildScrollBarAlloc(controlhandle parent, sdword ID, sdword x, sdword y, sdword width, sdword height, uicfunction function, udword flags) { featom *atom = (featom *)ID; scrollbarhandle newHandle; newHandle = (scrollbarhandle)regChildAlloc((regionhandle)parent, UIC_ScrollbarTab, x, y+20, width, height-40, uicStructureExtra(uicscrollbar), UIF_Button | RPE_WheelDown | RPE_WheelUp | RPE_HoldLeft | RPE_EnterHoldLeft); if (bitTest(atom->flags,FAF_Disabled)) bitSet(newHandle->reg.status,RSF_RegionDisabled); atom->pData = (ubyte *)newHandle; newHandle->isVertical = (bool8)(width < height); if (newHandle->isVertical) { newHandle->upbutton = (scrollbarbuttonhandle)regChildAlloc((regionhandle)parent, UIC_ScrollbarUpButton, x, y, width, 20, uicStructureExtra(uicscrollbarbutton), UIF_Button | RPE_WheelDown | RPE_WheelUp | RPE_HoldLeft | RPE_EnterHoldLeft); newHandle->upbutton->processFunction = NULL; // newHandle->upbutton->regionFilter = 0; newHandle->upbutton->contentColor = 0; newHandle->upbutton->borderColor = 0; newHandle->upbutton->screen = NULL; newHandle->upbutton->scrollbar = newHandle; regFunctionSet((regionhandle)newHandle->upbutton, uicScrollBarProcess); regDrawFunctionSet((regionhandle)newHandle->upbutton, uicScrollBarButtonDraw); newHandle->downbutton = (scrollbarbuttonhandle)regChildAlloc((regionhandle)parent, UIC_ScrollbarDownButton, x, y+height-20, width, 20, uicStructureExtra(uicscrollbarbutton), UIF_Button | RPE_WheelDown | RPE_WheelUp | RPE_HoldLeft | RPE_EnterHoldLeft); newHandle->downbutton->processFunction = NULL; // newHandle->downbutton->regionFilter = 0; newHandle->downbutton->contentColor = 0; newHandle->downbutton->borderColor = 0; newHandle->downbutton->screen = NULL; newHandle->downbutton->scrollbar = newHandle; regFunctionSet((regionhandle)newHandle->downbutton, uicScrollBarProcess); regDrawFunctionSet((regionhandle)newHandle->downbutton, uicScrollBarButtonDraw); newHandle->thumb.x0 = x+4; newHandle->thumb.y0 = y+20; newHandle->thumb.x1 = x+width-4; newHandle->thumb.y1 = y+height-40; newHandle->thumbreg = newHandle->reg.rect; newHandle->thumbreg.y0+=4; newHandle->thumbreg.y1-=4; } regFunctionSet((regionhandle)newHandle, uicScrollBarProcess); regDrawFunctionSet((regionhandle)newHandle, uicScrollBarDraw); newHandle->processFunction = function; // newHandle->regionFilter = 0; newHandle->mouseMoved = 0; return newHandle; } /*----------------------------------------------------------------------------- Name : uicChildListWindowAlloc Description : this allocates and initializes the listwindow uic element. Inputs : atom data Outputs : uiclistwindow structure handle Return : void ----------------------------------------------------------------------------*/ listwindowhandle uicChildListWindowAlloc(controlhandle parent, sdword ID, sdword x, sdword y, sdword width, sdword height, uicfunction function, udword flags) { featom *atom = (featom *)ID; listwindowhandle newHandle; rectangle prect; newHandle = (listwindowhandle)regChildAlloc((regionhandle)parent, ID, x, y, width, height, uicStructureExtra(uiclistwindow), UIF_Button | RPE_WheelDown | RPE_WheelUp | RPE_HoldLeft | RPE_EnterHoldLeft); if (bitTest(atom->flags,FAF_Disabled)) bitSet(newHandle->reg.status,RSF_RegionDisabled); atom->pData = (ubyte *)newHandle; prect.x0 = x; prect.x1 = x + width; prect.y0 = y; prect.y1 = y + height; regFunctionSet((regionhandle)newHandle, uicListWindowProcess); if (bitTest(atom->flags, FAF_Hidden)) { regDrawFunctionSet((regionhandle)newHandle, NULL); } else { regDrawFunctionSet((regionhandle)newHandle, uicListWindowDraw); } newHandle->processFunction = function; newHandle->titleprocess = NULL; newHandle->titledraw = NULL; newHandle->itemdraw = NULL; newHandle->windowflags = 0; newHandle->ListTotal = 0; newHandle->UpperIndex = 0; newHandle->MaxIndex = 0; newHandle->windowflags = 0; newHandle->TitleHeight = 0; newHandle->sorttype = -1; newHandle->sortOrder = TRUE; newHandle->topitem = NULL; listInit(&newHandle->listofitems); newHandle->CurLineSelected=NULL; return newHandle; } /*----------------------------------------------------------------------------- Name : uicListWindowInit Description : inititalizes the window with the information passed into. Inputs : listwindow, all info for initilization Outputs : none Return : none ----------------------------------------------------------------------------*/ void uicListWindowInit(listwindowhandle listwindow, listtitlebardraw titledraw, listtitlebarclick titleclick, sdword titleheight, listitemdraw itemdraw, sdword itemheight, udword flags) { listwindow->windowflags = flags; if (bitTest(flags,UICLW_CanHaveFocus)) listwindow->reg.flags |= RPE_KeyDown; if (titledraw != NULL) listwindow->windowflags |= UICLW_HasTitleBar; if (titleclick != NULL) listwindow->windowflags |= UICLW_CanClickOnTitle; listwindow->reg.flags |= RPE_DoubleLeft; listwindow->titledraw = titledraw; listwindow->titleprocess = titleclick; listwindow->TitleHeight = titleheight; listwindow->itemdraw = itemdraw; listwindow->itemheight = itemheight; listwindow->MaxIndex = (listwindow->reg.rect.y1 - titleheight - listwindow->reg.rect.y0 - (uicListWindowMargin*2)) / itemheight; uicListScrollBarAdjust(listwindow); } /*----------------------------------------------------------------------------- Name : uicListAddItem Description : adds an item to a the linked list of items and sets it up accordingly. Inputs : listwindow, item Outputs : none Return : none ----------------------------------------------------------------------------*/ listitemhandle uicListAddItem(listwindowhandle listwindow, ubyte *data, udword flags, udword where) { listitemhandle item; Node *walk, *recalc=NULL; sdword i = 1, pos; dbgAssert(listwindow!=NULL); item = (listitemhandle)memAlloc(sizeof(uiclistitem),"GameListElement",NonVolatile); item->data = data; item->flags = flags; if (listwindow->listofitems.num == 0) { listwindow->topitem = item; } if (where==UICLW_AddToHead) { if (listwindow->listofitems.head!=NULL) { recalc = &item->link; pos = ((listitemhandle)listGetStructOfNode(listwindow->listofitems.head))->position; listAddNodeBefore(listwindow->listofitems.head,&item->link, item); listwindow->topitem = item; } else { listAddNode(&listwindow->listofitems, &item->link, item); item->position = 0; } } else if (where==UICLW_AddToTail) { if (listwindow->listofitems.tail!=NULL) { item->position = ((listitemhandle)listGetStructOfNode(listwindow->listofitems.tail))->position+1; listAddNodeAfter(listwindow->listofitems.tail, &item->link, item); } else { listAddNode(&listwindow->listofitems, &item->link, item); item->position = 0; } } else { if (listwindow->listofitems.head!=NULL) { item->position = ((listitemhandle)listGetStructOfNode(listwindow->listofitems.tail))->position+1; listAddNode(&listwindow->listofitems, &item->link, item); } else { listAddNode(&listwindow->listofitems, &item->link, item); item->position = 0; } } while (recalc != NULL) { pos++; ((listitemhandle)listGetStructOfNode(recalc))->position = pos; recalc = recalc->next; } listwindow->ListTotal++; #ifdef DEBUG_STOMP regVerify(&listwindow->reg); #endif regRecursiveSetDirty(&listwindow->reg); regDirtyScreensAboveRegion(&listwindow->reg); // listwindow->reg.status |= RSF_DrawThisFrame; if ( (listwindow->ListTotal > listwindow->MaxIndex) && (listwindow->windowflags & UICLW_AutoScroll) && (!(listwindow->windowflags & UICLW_AutoScrollOff))) { walk = listwindow->listofitems.tail; listwindow->UpperIndex = listwindow->ListTotal-1; while ( (walk->prev != NULL) && (iMaxIndex) ) { i++; listwindow->UpperIndex--; walk = walk->prev; } listwindow->topitem = (listitemhandle)listGetStructOfNode(walk); } if (bitTest(flags,UICLI_Selected)) { listwindow->CurLineSelected = item; uicListWindowViewSelection(listwindow); } uicListScrollBarAdjust(listwindow); return (item); } /*----------------------------------------------------------------------------- Name : uicListFindItemByData Description : returns a listitemhandle which has data data in it, NULL if not found Inputs : Outputs : Return : returns a listitemhandle which has data data in it, NULL if not found ----------------------------------------------------------------------------*/ listitemhandle uicListFindItemByData(listwindowhandle listwindow, ubyte *data) { Node *walk; listitemhandle item; walk = listwindow->listofitems.head; while (walk != NULL) { item = listGetStructOfNode(walk); if (item->data == data) { return item; } walk = walk->next; } return NULL; } /*----------------------------------------------------------------------------- Name : uicListRemoveItemByData Description : remove a item from the list by its data Inputs : Outputs : Return : remove a item from the list by its data ----------------------------------------------------------------------------*/ void uicListRemoveItemByData(listwindowhandle listwindow, ubyte *data) { listitemhandle item = uicListFindItemByData(listwindow,data); if (item) { uicListRemoveItem(listwindow,item); } } /*----------------------------------------------------------------------------- Name : uicListFindFirstItem Description : returns the first item in a listwindow, or NULL Inputs : Outputs : Return : ----------------------------------------------------------------------------*/ listitemhandle uicListFindFirstItem(listwindowhandle listwindow) { if (listwindow->listofitems.head != NULL) { return listGetStructOfNode(listwindow->listofitems.head); } else { return NULL; } } /*----------------------------------------------------------------------------- Name : uicListRemoveAllItems Description : removes every item from a listwindow Inputs : Outputs : Return : ----------------------------------------------------------------------------*/ void uicListRemoveAllItems(listwindowhandle listwindow) { listitemhandle item; for (;;) { item = uicListFindFirstItem(listwindow); if (item == NULL) { break; } uicListRemoveItem(listwindow, item); } } /*----------------------------------------------------------------------------- Name : uicListRemoveItem Description : removes an item from the list linked list of items and sets it up accordingly. Inputs : listwindow, item Outputs : none Return : none ----------------------------------------------------------------------------*/ void uicListRemoveItem(listwindowhandle listwindow, listitemhandle item) { Node *walk,*count; bool found=FALSE; listitemhandle iteminfo, newpos; sdword i, relativecount; walk = listwindow->listofitems.head; while (walk != NULL) { if (item == listGetStructOfNode(walk)) { found = TRUE; break; } walk = walk->next; } if (found) { iteminfo = (listitemhandle)listGetStructOfNode(walk); count = walk->next; relativecount = iteminfo->position; if (iteminfo == listwindow->topitem) { listDeleteNode(walk); listwindow->ListTotal--; if (listwindow->listofitems.num != 0) { listwindow->topitem = (listitemhandle)listGetStructOfNode(listwindow->listofitems.head); listwindow->UpperIndex = 0; } else listwindow->topitem = NULL; } else { listwindow->ListTotal--; listDeleteNode(walk); i=0; walk = listwindow->listofitems.head; while (walk != NULL) { if (listGetStructOfNode(walk) == listwindow->topitem) { break; } i++; walk = walk->next; } listwindow->UpperIndex = i; } if (count != NULL) { newpos = listGetStructOfNode(count); newpos->position = relativecount; relativecount++; count = count->next; } uicListScrollBarAdjust(listwindow); #ifdef DEBUG_STOMP regVerify(&listwindow->reg); #endif regRecursiveSetDirty(&listwindow->reg); regDirtyScreensAboveRegion(&listwindow->reg); // listwindow->reg.status |= RSF_DrawThisFrame; } } /*----------------------------------------------------------------------------- Name : uicListCleanUp Description : free's all memory allocated for the list of items. Inputs : listwindow, item Outputs : none Return : none ----------------------------------------------------------------------------*/ void uicListCleanUp(listwindowhandle listwindow) { listDeleteAll(&listwindow->listofitems); listwindow->topitem = NULL; listwindow->ListTotal = 0; listwindow->UpperIndex = 0; } /*----------------------------------------------------------------------------- Name : uicListSort Description : free's all memory allocated for the list of items. Inputs : listwindow, item Outputs : none Return : none ----------------------------------------------------------------------------*/ void uicListSort(listwindowhandle listwindow, MergeSortCompareCb compare) { Node *walk; sdword index; listitemhandle item; if (listwindow->ListTotal>0) { listMergeSortGeneral(&listwindow->listofitems, compare); walk = listwindow->listofitems.head; index = 0; while (walk != NULL) { item = listGetStructOfNode(walk); item->position = index; index++; walk = walk->next; } listwindow->topitem = listGetStructOfNode(listwindow->listofitems.head); listwindow->UpperIndex = 0; uicListScrollBarAdjust(listwindow); } } /*----------------------------------------------------------------------------- Name : uicListWindowSetCurItem Description : Sets the currently selected item to item. Inputs : listwindow and item to set to currently selected. Outputs : Return : ----------------------------------------------------------------------------*/ void uicListWindowSetCurItem(listwindowhandle listhandle, listitemhandle item) { if (listhandle->CurLineSelected!=NULL) { bitClear(listhandle->CurLineSelected->flags, UICLI_Selected); } listhandle->CurLineSelected = item; if (listhandle->CurLineSelected!= NULL) { bitSet(listhandle->CurLineSelected->flags, UICLI_Selected); uicListWindowViewSelection(listhandle); } } /*----------------------------------------------------------------------------- Name : uicTextBufferResize Description : Resize the buffer in a text entry box Inputs : entry - the text entry who's buffer we are resizing Outputs : Return : ----------------------------------------------------------------------------*/ void uicTextBufferResize(textentryhandle entry, sdword size) { sdword currentLength; regVerify(&entry->reg); if (entry->textBuffer != NULL) { //get the length of the string in the text box currentLength = strlen(entry->textBuffer); } else { currentLength = 0; } entry->textBuffer = memRealloc(entry->textBuffer, size, "TextEntryBuffer", 0); if (currentLength >= size) { //if string extends past the end of the buffer entry->textBuffer[0] = 0; } else if (currentLength == 0) { //or if there was no string memset(entry->textBuffer, 0, size); //clear the buffer to all zeros } entry->bufferLength = size; } /*----------------------------------------------------------------------------- Name : uicTextEntryCleanUp Description : Cleans up the text entry boxes buffers. Inputs : entry - the text entry who's buffer we are freeing buffers for. Outputs : Return : ----------------------------------------------------------------------------*/ void uicTextEntryCleanUp(textentryhandle entry) { if (entry->textBuffer != NULL) { memFree(entry->textBuffer); } } /*----------------------------------------------------------------------------- Name : uicTextEntrySet Description : Set the text to be edited in a text entry control. Inputs : entry - what control to adjust text - the text to be copied into it's edit buffer. Will be truncated and NULL-terminated if needed. cursorPos - position of the cursor Outputs : Return : ----------------------------------------------------------------------------*/ void uicTextEntrySet(textentryhandle entry, char *text, sdword cursorPos) { sdword length = strlen(text); memset(entry->textBuffer,0,entry->bufferLength*sizeof(char)); regVerify(&entry->reg); if (length >= entry->bufferLength - 1) { //if text too long memcpy(entry->textBuffer, text, entry->bufferLength);//truncated copy entry->textBuffer[entry->bufferLength - 1] = 0; //null-terminate } else { strcpy(entry->textBuffer, text); //else straight copy } entry->iCharacter = min(cursorPos, min(entry->bufferLength - 1, length)); if (entry->iCharacter < 0) entry->iCharacter=0; uicRepositionText(entry, TRUE); //reposition the text } /*----------------------------------------------------------------------------- Name : uicTextEntryGet Description : Get a copy of the text in a text entry control. Inputs : entry - text entry control to read maxLength - length of the buffer we are to store the text into. Outputs : dest - where to store the text Return : Note : If you just need a temporary reference to the text, you can read entry->textBuffer directly. ----------------------------------------------------------------------------*/ void uicTextEntryGet(textentryhandle entry, char *dest, sdword maxLength) { sdword length = min(maxLength, entry->bufferLength); memStrncpy(dest, entry->textBuffer, length); //entry->textBuffer[length - 1] = 0; } /*----------------------------------------------------------------------------- Name : uicTextEntryInit Description : initilizes different flags for the text entry box. Inputs : textentryhandle, flags to set. Outputs : none Return : void ----------------------------------------------------------------------------*/ void uicTextEntryInit(textentryhandle entry, udword flags) { entry->textflags|=flags; } /*----------------------------------------------------------------------------- Name : uicChildTextEntryAlloc Description : Allocate and initialize a text entry control. Inputs : parent - parent of the new retion atom - atom to use for this region x, y - location of region width, height - size of the text entry region filter - currently not used. But maybe one day! Outputs : Return : ----------------------------------------------------------------------------*/ textentryhandle uicChildTextEntryAlloc(controlhandle parent, featom *atom, sdword x, sdword y, sdword width, sdword height, udword filter) { textentryhandle newHandle; newHandle = (textentryhandle)regChildAlloc((regionhandle)parent, (sdword)atom, x, y, width, height, uicStructureExtra(uictextentry), UIF_TextEntry); if (bitTest(atom->flags,FAF_Disabled)) bitSet(newHandle->reg.status,RSF_RegionDisabled); atom->pData = (ubyte *)newHandle; regFunctionSet((regionhandle)newHandle, uicTextEntryProcess); regDrawFunctionSet((regionhandle)newHandle, uicTextEntryDraw); // newHandle->regionFilter = 0xffffffff; //!!!! newHandle->contentColor = atom->contentColor; //default colors newHandle->borderColor = atom->borderColor; newHandle->screen = NULL; //will be set later newHandle->textBuffer = NULL; uicTextBufferResize(newHandle, UTE_DefaultBufferSize); //default text buffer size newHandle->bufferLength = UTE_DefaultBufferSize; newHandle->iCharacter = 0; //no text yet newHandle->iVisible = 0; //start with the first character visible newHandle->currentFont = frFontRegister("default.hff"); //give it a default font newHandle->flashRate = utyCaretBlinkRate(); //default blink rate newHandle->textRect = newHandle->reg.rect; newHandle->textflags = 0; if (bitTest(atom->flags, FAF_BorderVisible)) { //if there is a border newHandle->textRect.x0 += FBA_TextEntry+5; //adjust the text rectangle in a bit newHandle->textRect.x1 -= FBA_TextEntry+5; newHandle->textRect.y0 += FBA_TextEntry; newHandle->textRect.y1 -= FBA_TextEntry; } return(newHandle); } /*----------------------------------------------------------------------------- Name : uicControlDelete Description : Delete a control, regardless of it's type Inputs : handle - handle of the control to delete Outputs : Memory freed up, links fixed up Return : void ----------------------------------------------------------------------------*/ void uicControlDelete(controlhandle handle) { featom *atom = (featom *)handle->userID; regRegionDelete((regionhandle)handle); if (atom->type == FA_TextEntry) { //free a text entry's buffer if (((textentryhandle)handle)->textBuffer != NULL) { memFree(((textentryhandle)handle)->textBuffer); } } } /*----------------------------------------------------------------------------- Name : uicFindFlag Description : finds the flagged region in the list Inputs : find - starting region for search. flag - flag searched for Outputs : None Return : region containing flag ----------------------------------------------------------------------------*/ regionhandle uicFindFlag(regionhandle find, udword flag, uword type) { // "find" represents the region created for the and key // callbacks. We want to start our search at the beginning of the // list of regions - find->parent is the base region and // find->parent->child is the start of the list of regions that are // the children of the base region. Following the linked list starting // with find->parent->child->next will eventually lead us back to the // starting point // we want to end our search when we reach the regions created // for the key callbacks because the addresses of temp->userID would // cause the computer to crash, therefore ending the search // when temp->userID < 256 fescreen *screen = feStack[feStackIndex].screen; sdword i; if (screen == NULL) { return(NULL); } for (i=1;inAtoms;i++) { if (type == ATOM_FLAG) { if (bitTest(screen->atoms[i].flags, flag)) { return((regionhandle)screen->atoms[i].region); } } else if ( (type == REGION_FLAG) && (screen->atoms[i].region != NULL) ) { if (bitTest( ((regionhandle)screen->atoms[i].region)->status, flag)) { return((regionhandle)screen->atoms[i].region); } } } return NULL; } /*----------------------------------------------------------------------------- Name : uicFindFlagGetAtom Description : finds the flagged region in the list Inputs : find - starting region for search. flag - flag searched for Outputs : None Return : region containing flag ----------------------------------------------------------------------------*/ featom *uicFindFlagGetAtom(regionhandle find, udword flag, uword type) { // "find" represents the region created for the and key // callbacks. We want to start our search at the beginning of the // list of regions - find->parent is the base region and // find->parent->child is the start of the list of regions that are // the children of the base region. Following the linked list starting // with find->parent->child->next will eventually lead us back to the // starting point // we want to end our search when we reach the regions created // for the key callbacks because the addresses of temp->userID would // cause the computer to crash, therefore ending the search // when temp->userID < 256 fescreen *screen = feStack[feStackIndex].screen; sdword i; if (screen == NULL) { return(NULL); } for (i=1;inAtoms;i++) { if (type == ATOM_FLAG) { if (bitTest(screen->atoms[i].flags, flag)) { return(&screen->atoms[i]); } } else if ( (type == REGION_FLAG) && (screen->atoms[i].region != NULL) ) { if (bitTest( ((regionhandle)screen->atoms[i].region)->status, flag)) { return(&screen->atoms[i]); } } } return NULL; } /*----------------------------------------------------------------------------- Name : uicFindTabstop Description : finds the region in the list with a tabstop matching feTabStop Inputs : find - starting region for search. Function gets to the beginning of the linked list which contains "find" and searches the list Outputs : None Return : found region or NULL if not found ----------------------------------------------------------------------------*/ regionhandle uicFindTabstop(regionhandle find) { /* regionhandle temp = find->parent->child; // "find" represents the region created for the and key // callbacks. We want to start our search at the beginning of the // list of regions - find->parent is the base region and // find->parent->child is the start of the list of regions that are // the children of the base region. Following the linked list starting // with find->parent->child->next will eventually lead us back to the // starting point while (temp != NULL) { if (temp->tabstop == feTabStop) { return (temp); } temp = temp->next; }*/ fescreen *screen = feStack[feStackIndex].screen; sdword i; if (screen == NULL) return NULL; for (i=0;inAtoms;i++) { if (screen->atoms[i].tabstop == feTabStop) { if (screen->atoms[i].type==FA_RadioButton) { return (feFindRadioButtonRegion(screen->atoms[i].region, TRUE)); } else return ((regionhandle)screen->atoms[i].region); } } return NULL; } /*----------------------------------------------------------------------------- Name : uicFindButtonType Description : Finds the buttontype of the callback region Inputs : reg - callback region Outputs : Return : button type ----------------------------------------------------------------------------*/ enum tagFIBAtomFlagSff uicFindButtonType(struct tagRegion *reg) { struct tagRegion *temp; temp = uicFindTabstop(reg); return ((enum tagFIBAtomFlagsff)((featom *)temp->userID)->type); } /*----------------------------------------------------------------------------- Name : uicClearCurrent Description : Clears the current button flag on the currently selected button Inputs : reg - callback region Outputs : Return : ----------------------------------------------------------------------------*/ bool uicClearCurrent(regionhandle reg) { regionhandle temp=NULL; textentryhandle entry; listwindowhandle listwindow; featom *atom; // when not initialized properly, the CurrentSelected flag is set // on non-button regions, so we'll clear all regions with // RSF_CurrentSelected set. Overkill usually, but fixes the problem atom = uicFindFlagGetAtom(reg, RSF_CurrentSelected, REGION_FLAG); if (atom != NULL) { temp = (regionhandle)atom->region; } if (temp!=NULL) { if (atom->type==FA_RadioButton) { atom = feAtomFindInScreen(feStack[feStackIndex].screen, atom->name); do { #ifdef DEBUG_STOMP regVerify((regionhandle)atom->region); #endif bitClear(((regionhandle)atom->region)->status,RSF_CurrentSelected); // bitSet(((regionhandle)atom->region)->status,RSF_DrawThisFrame); regRecursiveSetDirty((regionhandle)atom->region); } while ((atom = feAtomFindNextInScreen(feStack[feStackIndex].screen, atom, atom->name)) != NULL); } bitClear(temp->status, RSF_CurrentSelected); #ifdef DEBUG_STOMP regVerify(temp); #endif regRecursiveSetDirty(temp); // bitSet(temp->status, RSF_DrawThisFrame); if ( (((featom *)temp->userID) != NULL) && (((featom *)temp->userID)->type==FA_TextEntry) ) { entry = (textentryhandle)temp; atom = (featom *)temp->userID; entry->message = CM_LoseFocus; feFunctionExecute(atom->name, atom, FALSE); bitClear(temp->status,RSF_KeyCapture); regKeysFocussed = FALSE; } if ( (((featom *)temp->userID) != NULL) && (((featom *)temp->userID)->type==FA_ListWindow) ) { listwindow = (listwindowhandle)temp; atom = (featom *)temp->userID; if (bitTest(listwindow->windowflags,UICLW_CanHaveFocus)) { listwindow->message = CM_LoseFocus; feFunctionExecute(atom->name, atom, FALSE); bitClear(listwindow->windowflags, UICLW_GetKeyPressed); bitClear(temp->status,RSF_KeyCapture); regKeysFocussed = FALSE; } } if (temp->tabstop != 0) return TRUE; } return FALSE; } /*----------------------------------------------------------------------------- Name : uicSetCurrent Description : Set the current button flag on the button corresponding to the tabstop key - only makes the change if the button is on the topmost menu. Inputs : reg - callback region bUserInput - change of focus due to user input Outputs : Return : ----------------------------------------------------------------------------*/ void uicSetCurrent(regionhandle reg, bool bUserInput) { listwindowhandle listwindow; featom *atom, *radio; if (reg != NULL) { if (bitTest(reg->status,RSF_CantFocusTo)) { return; } if (!bitTest(reg->status, RSF_CurrentSelected)) { bitSet(reg->status, RSF_CurrentSelected); if (reg->tabstop != 0) feTabStop = reg->tabstop; #ifdef DEBUG_STOMP regVerify(reg); #endif regRecursiveSetDirty(reg); // bitSet(reg->status, RSF_DrawThisFrame); } radio = reg->atom; // if (radio->type==FA_RadioButton) { atom = feAtomFindInScreen(feStack[feStackIndex].screen, radio->name); do { if (atom->tabstop != 0) feTabStop = reg->tabstop; #ifdef DEBUG_STOMP regVerify((regionhandle)atom->region); #endif bitSet(((regionhandle)atom->region)->status,RSF_CurrentSelected); regRecursiveSetDirty((regionhandle)atom->region); // bitSet(((regionhandle)atom->region)->status,RSF_DrawThisFrame); } while ((atom = feAtomFindNextInScreen(feStack[feStackIndex].screen, atom, radio->name)) != NULL); } //text entry special case: if tabbing into a text entry region, you can start typing if (reg->processFunction == uicTextEntryProcess) { bitSet(reg->status, RSF_KeyCapture); keyBufferClear(); regKeysFocussed = TRUE; } if (reg->processFunction == uicListWindowProcess) { listwindow = (listwindowhandle)reg; if (bitTest(listwindow->windowflags,UICLW_CanHaveFocus)) { bitSet(reg->status, RSF_KeyCapture); keyBufferClear(); regKeysFocussed = TRUE; } } } } /*----------------------------------------------------------------------------- Name : uicLimitTabstop Description : Ensures that the tabstop variable is not larger than the number of buttons on the screen or smaller than 1 Inputs : num_buttons - number of buttons on the screen Outputs : Return : ----------------------------------------------------------------------------*/ void uicLimitTabstop(sdword num_buttons) { if (feTabStop > (udword)num_buttons) { feTabStop = 1; } else if (feTabStop == 0) { feTabStop = num_buttons; } } /*----------------------------------------------------------------------------- Name : uicTabProcess Description : Changes the glabal tabstop variable when the Tab (or Shift-Tab) key is pressed Inputs : num_buttons (other variables are placeholders) Outputs : tabstop incremented by 1 if the shift key is up or decremented by 1 if shift key is down. Return : 0 (placeholder) ----------------------------------------------------------------------------*/ udword uicTabProcess(struct tagRegion *reg, sdword num_buttons, udword event, udword data) { regionhandle temp; uicFocusToKeyboard(); if (uicClearCurrent(reg)) { if (keyIsHit(SHIFTKEY)) { --feTabStop; } else { ++feTabStop; } uicLimitTabstop(num_buttons); } temp = uicFindTabstop(reg); uicSetCurrent(temp, TRUE); return 0; } /*----------------------------------------------------------------------------- Name : uicRightArrowProcess Description : Inputs : reg - callback region (other variables are placeholders) Outputs : Return : 0 (placeholder) ----------------------------------------------------------------------------*/ udword uicRightArrowProcess(struct tagRegion *reg, sdword num_buttons, udword event, udword data) { struct tagRegion *temp; featom *radio, *atom; sdword index; uicFocusToKeyboard(); radio = uicFindFlagGetAtom(reg, RSF_CurrentSelected, REGION_FLAG); if (radio->type==FA_RadioButton) { temp = feFindRadioButtonRegion(radio->region, TRUE); if (temp != NULL) { radio = temp->atom; index = (sdword)radio->pData; index++; if (index < 0) { return 0; } atom = feAtomFindInScreen(feStack[feStackIndex].screen, radio->name); do { if ((sdword)atom->pData == index) { uicFocusToKeyboard(); uicClearCurrent(radio->region); uicSetCurrent(atom->region, TRUE); uicRadioButtonProcess((regionhandle)atom->region,(sdword)atom, RPE_KeyDown, 0); return 0; } } while ((atom = feAtomFindNextInScreen(feStack[feStackIndex].screen, atom, atom->name)) != NULL); } } else { uicFocusToKeyboard(); uicClearCurrent(reg); feTabStop++; uicLimitTabstop(num_buttons); temp = uicFindTabstop(reg); uicSetCurrent(temp, TRUE); return 0; } return 0; } /*----------------------------------------------------------------------------- Name : uicLeftArrowProcess Description : Inputs : reg - callback region (other variables are placeholders) Outputs : Return : 0 (placeholder) ----------------------------------------------------------------------------*/ udword uicLeftArrowProcess(struct tagRegion *reg, sdword num_buttons, udword event, udword data) { struct tagRegion *temp; featom *radio, *atom; sdword index; uicFocusToKeyboard(); radio = uicFindFlagGetAtom(reg, RSF_CurrentSelected, REGION_FLAG); if (radio->type==FA_RadioButton) { temp = feFindRadioButtonRegion(radio->region, TRUE); if (temp != NULL) { radio = temp->atom; index = (sdword)radio->pData; index--; if (index < 0) { return 0; } atom = feAtomFindInScreen(feStack[feStackIndex].screen, radio->name); do { if ((sdword)atom->pData == index) { uicFocusToKeyboard(); uicClearCurrent(radio->region); uicSetCurrent(atom->region, TRUE); uicRadioButtonProcess((regionhandle)atom->region, (sdword)atom, RPE_KeyDown, 0); return 0; } } while ((atom = feAtomFindNextInScreen(feStack[feStackIndex].screen, atom, atom->name)) != NULL); } } else { uicFocusToKeyboard(); uicClearCurrent(reg); feTabStop--; uicLimitTabstop(num_buttons); temp = uicFindTabstop(reg); uicSetCurrent(temp, TRUE); return 0; } return 0; } /*----------------------------------------------------------------------------- Name : uicUpArrowProcess Description : Inputs : reg - callback region (other variables are placeholders) Outputs : Return : 0 (placeholder) ----------------------------------------------------------------------------*/ udword uicUpArrowProcess(struct tagRegion *reg, sdword num_buttons, udword event, udword data) { struct tagRegion *temp; uicFocusToKeyboard(); uicClearCurrent(reg); feTabStop--; uicLimitTabstop(num_buttons); temp = uicFindTabstop(reg); uicSetCurrent(temp, TRUE); return 0; } /*----------------------------------------------------------------------------- Name : uicDownArrowProcess Description : Inputs : reg - callback region (other variables are placeholders) Outputs : Return : 0 (placeholder) ----------------------------------------------------------------------------*/ udword uicDownArrowProcess(struct tagRegion *reg, sdword num_buttons, udword event, udword data) { struct tagRegion *temp; uicFocusToKeyboard(); uicClearCurrent(reg); feTabStop++; uicLimitTabstop(num_buttons); temp = uicFindTabstop(reg); uicSetCurrent(temp, TRUE); return 0; } /*----------------------------------------------------------------------------- Name : uicSpacebarProcess Description : Activates the current button Inputs : reg - callback region (other variables are placeholders) Outputs : current button callback Return : 0 (placeholder) ----------------------------------------------------------------------------*/ udword uicSpacebarProcess(struct tagRegion *reg, sdword num_buttons, udword event, udword data) { regionhandle temp; enum tagFIBAtomFlagsff buttonType; featom *atom, *radio; sdword index, max; uicFocusToKeyboard(); temp = uicFindFlag(reg, RSF_CurrentSelected, REGION_FLAG); // backup if (for some reason) the RSF_CurrentSelected flag is not set if (temp == NULL) { //temp = uicFindTabstop(reg); return 0; } buttonType = (enum tagFIBAtomFlagsff)((featom *)temp->userID)->type; switch (buttonType) { case FA_Button: if (uicButtonProcess(temp, temp->userID, RPE_KeyDown, 0)==RPR_Redraw) { #ifdef DEBUG_STOMP regVerify(temp); #endif regRecursiveSetDirty(temp); // temp->status |= RSF_DrawThisFrame; } break; case FA_CheckBox: case FA_ToggleButton: if (uicToggleProcess(temp, temp->userID, RPE_KeyDown, 0)==RPR_Redraw) { #ifdef DEBUG_STOMP regVerify(temp); #endif regRecursiveSetDirty(temp); // temp->status |= RSF_DrawThisFrame; } break; case FA_RadioButton: temp = feFindRadioButtonRegion(temp, TRUE); if (temp != NULL) { radio = temp->atom; index = (sdword)radio->pData; index++; max = 0; atom = feAtomFindInScreen(feStack[feStackIndex].screen, radio->name); do { if ((sdword)atom->pData > max) max = (sdword)atom->pData; if ((sdword)atom->pData == index) { uicFocusToKeyboard(); uicRadioButtonProcess((regionhandle)atom->region, (sdword)atom, RPE_KeyDown, 0); return 0; } } while ((atom = feAtomFindNextInScreen(feStack[feStackIndex].screen, atom, atom->name)) != NULL); atom = feAtomFindInScreen(feStack[feStackIndex].screen, radio->name); do { if ((sdword)atom->pData == 0) { uicFocusToKeyboard(); uicRadioButtonProcess((regionhandle)atom->region, (sdword)atom, RPE_KeyDown, 0); return 0; } } while ((atom = feAtomFindNextInScreen(feStack[feStackIndex].screen, atom, atom->name)) != NULL); } break; default: break; } return 0; } /*----------------------------------------------------------------------------- Name : uicReturnProcess Description : Activates the default OK button or the tabstop button Inputs : reg - callback region (other variables are placeholders) Outputs : "OK" button callback Return : 0 (placeholder) ----------------------------------------------------------------------------*/ udword uicReturnProcess(struct tagRegion *reg, sdword num_buttons, udword event, udword data) { struct tagRegion *temp; featom *atom; uicFocusToKeyboard(); temp = uicFindFlag(reg, FAF_DefaultOK, ATOM_FLAG); if (temp == NULL) { temp = uicFindTabstop(reg); } if (temp != NULL) { atom = (featom *)temp->userID; switch (atom->type) { case FA_Button: case FA_CheckBox: case FA_ToggleButton: if (((buttonhandle)temp)->processFunction(temp, temp->userID, CM_ButtonClick, 0)==RPR_Redraw) { #ifdef DEBUG_STOMP regVerify(temp); #endif // temp->status |= RSF_DrawThisFrame; regRecursiveSetDirty(temp); } break; case FA_TextEntry: ((textentryhandle)((featom *)temp->userID)->pData)->message = CM_GainFocus; bitSet(temp->status, RSF_KeyCapture); keyBufferClear(); regKeysFocussed = TRUE; feFunctionExecute(((featom *)temp->userID)->name, (featom *)temp->userID, FALSE); break; default: dbgMessagef("\nuicReturnProcess: don't know how to handle return for atom of type 0x%x", atom->type); } } return 0; } /*----------------------------------------------------------------------------- Name : uicEscProcess Description : Activates the default back button Inputs : reg - callback region (other variables are placeholders) Outputs : "back" button callback Return : 0 (placeholder) ----------------------------------------------------------------------------*/ udword uicEscProcess(struct tagRegion *reg, sdword num_buttons, udword event, udword data) { struct tagRegion *temp; uicFocusToKeyboard(); temp = uicFindFlag(reg, FAF_DefaultBack, ATOM_FLAG); if (temp != NULL) { ((buttonhandle)temp)->processFunction(temp, temp->userID, CM_ButtonClick, 0); soundEvent(NULL, UI_Click); } return 0; } /*----------------------------------------------------------------------------- Name : uicHomeProcess Description : Changes the glabal tabstop variable when the Home key is pressed Inputs : num_buttons (other variables are placeholders) Outputs : tabstop = 1 Return : 0 (placeholer) ----------------------------------------------------------------------------*/ udword uicHomeProcess(struct tagRegion *reg, sdword num_buttons, udword event, udword data) { struct tagRegion *temp; uicFocusToKeyboard(); uicClearCurrent(reg); feTabStop = 1; temp = uicFindTabstop(reg); uicSetCurrent(temp, TRUE); return 0; } /*----------------------------------------------------------------------------- Name : uicEndProcess Description : Changes the glabal tabstop variable when the End key is pressed Inputs : num_buttons (other variables are placeholders) Outputs : tabstop = num_buttons Return : 0 (placeholer) ----------------------------------------------------------------------------*/ udword uicEndProcess(struct tagRegion *reg, sdword num_buttons, udword event, udword data) { struct tagRegion *temp; uicFocusToKeyboard(); uicClearCurrent(reg); feTabStop = num_buttons; temp = uicFindTabstop(reg); uicSetCurrent(temp, TRUE); return 0; }