hschumann2/TempleOS-Source-Code
0832
1 2#help_index "Menus"3#help_file "::/Doc/Menus"4 5CTask *MenuTask()6{7 CTask *res=sys_focus_task;8 while (res && !res->cur_menu)9 res=res->parent_task;10 return res;11}12 13CMenuEntry *sys_cur_submenu_entry=NULL;14 15public CMenuEntry *MenuSubEntryFind(16 CMenuEntry *haystack_first,U8 *needle_entry_name)17{//You probably don't need this. Use dir / and MenuEntryFind().18 while (haystack_first) {19 if (!StrCmp(haystack_first->name,needle_entry_name))20 return haystack_first;21 haystack_first=haystack_first->next;22 }23 return NULL;24}25 26public CMenuEntry *MenuEntryFind(CMenu *haystack_menu,U8 *needle_full_name)27{//Find pulldown entry. Fs->cur_menu is probably the menu you want.28//Just 2 levels -- across top and down are valid, currently.29 U8 *st,*st2;30 CMenuEntry *tmpse;31 if (!haystack_menu || !needle_full_name)32 return NULL;33 st=StrNew(needle_full_name);34 st2=StrNew(needle_full_name);35 tmpse=(&haystack_menu->sub)(U8 *)-offset(CMenuEntry.sub);36 while (*st && tmpse) {37 StrFirstRem(st,"/",st2);38 tmpse=MenuSubEntryFind(tmpse->sub,st2);39 }40 Free(st);41 Free(st2);42 return tmpse;43}44 45CMenuEntry *MenuNewSub(CCmpCtrl *cc,CTask *task)46{47 CMenuEntry *tmpme=NULL,*tmpse;48 if (cc->token==TK_IDENT) {49 tmpme=CAlloc(sizeof(CMenuEntry),task);50 if (StrLen(cc->cur_str)>31)51 cc->cur_str[31]=0;52 StrCpy(tmpme->name,cc->cur_str);53 if (Lex(cc)=='(') {54 tmpme->msg_code=MSG_KEY_DOWN_UP;55 if (Lex(cc)!=',' && cc->token!=')')56 tmpme->msg_code=LexExpressionI64(cc);57 if (cc->token==',')58 Lex(cc);59 if (cc->token!=',' && cc->token!=')')60 tmpme->arg1=LexExpressionI64(cc);61 if (cc->token==',')62 Lex(cc);63 if (cc->token!=',' && cc->token!=')')64 tmpme->arg2=LexExpressionI64(cc);65 if (cc->token!=')')66 LexExcept(cc,"Missing ')' at ");67 if (Lex(cc)!=';')68 LexExcept(cc,"Missing ';' at");69 Lex(cc); //Skip ;70 } else if (cc->token=='{') {71 Lex(cc); //Skip {72 tmpme->dir=TRUE;73 tmpse=&tmpme->sub;74 while (tmpse && cc->token!='}')75 tmpse=tmpse->next=MenuNewSub(cc,task);76 if (cc->token!='}')77 LexExcept(cc,"Missing '}' at ");78 else79 Lex(cc); //Skip }80 } else81 LexExcept(cc,"Expecting '{' at ");82 }83 return tmpme;84}85 86public CMenu *MenuNew(U8 *st,I64 flags=0,CTask *task=NULL)87{//Parse a menu. You probably don't need this.88 CMenu *m;89 CMenuEntry *tmpse;90 CCmpCtrl *cc=CmpCtrlNew(st,CCF_DONT_FREE_BUF);91 if (!task) task=Fs;92 Lex(cc);93 m=CAlloc(sizeof(CMenu),task);94 m->task=task;95 m->flags=flags;96 m->attr =BLUE<<4+YELLOW;97 tmpse=&m->sub;98 while (tmpse)99 tmpse=tmpse->next=MenuNewSub(cc,task);100 CmpCtrlDel(cc);101 return m;102}103 104public CMenu *MenuFile(U8 *filename,I64 flags=0,CTask *task=NULL)105{//Parse a pulldown menu file. You probably don't need this.106 CMenu *m;107 U8 *st=MStrPrint("#include \"%s\"",filename);108 m=MenuNew(st,flags,task);109 Free(st);110 return m;111}112 113U0 MenuDelSub(CMenuEntry *tmpme)114{115 CMenuEntry *tmpse,*tmpse1;116 if (tmpme) {117 tmpse=tmpme->sub;118 while (tmpse) {119 tmpse1=tmpse->next;120 MenuDelSub(tmpse);121 tmpse=tmpse1;122 }123 Free(tmpme);124 }125}126 127public U0 MenuDel(CMenu *m)128{//Delete a manu. You probably don't need this.129 CMenuEntry *tmpme,*tmpme1;130 if (!m) return;131 tmpme=m->sub;132 while (tmpme) {133 tmpme1=tmpme->next;134 MenuDelSub(tmpme);135 tmpme=tmpme1;136 }137 Free(m);138}139 140I64 MenuEntryWidth(CMenuEntry *tmpme)141{142 I64 res=StrLen(tmpme->name);143 CMenuEntry *tmpse=tmpme->sub;144 while (tmpse) {145 res=MaxI64(res,StrLen(tmpse->name));146 tmpse=tmpse->next;147 }148 return res+1;149}150 151public CMenu *MenuPush(U8 *st)152{//Save old pulldown menu and replace with new from str.153 CMenu *m=MenuNew(st);154 m->next=Fs->cur_menu;155 Fs->cur_menu=m;156 return m;157}158 159public CMenu *MenuFilePush(U8 *filename)160{//Save old pulldown menu and replace with new from file.161 CMenu *m=MenuFile(filename);162 m->next=Fs->cur_menu;163 Fs->cur_menu=m;164 return m;165}166 167public U0 MenuPop()168{//Restore old pulldown menu. Delete just-deactivated menu.169 CMenu *m=Fs->cur_menu;170 if (!m) return;171 Fs->cur_menu=m->next;172 MenuDel(m);173}174 175U0 DrawMenu(CDC *dc)176{177 CMenu *m;178 CMenuEntry *tmpme,*tmpse,*cur_submenu=NULL;179 U8 *st=NULL;180 CTask *task=MenuTask;181 I64 i,w,x0,y0,x1=ms.pos.x,y1=ms.pos.y;182 if (!TaskValidate(task) || !(m=task->cur_menu)) {183 sys_cur_submenu_entry=NULL;184 return;185 }186 dc->color=m->attr>>4;187 GrRect(dc,0,0,GR_WIDTH,FONT_HEIGHT);188 x0=0;189 tmpme=m->sub;190 while (tmpme) {191 w=MenuEntryWidth(tmpme)*FONT_WIDTH;192 if (x0<=x1<x0+w) {193 if (0<=y1<FONT_HEIGHT) {194 dc->color=m->attr&15;195 GrRect(dc,x0,0,w,FONT_HEIGHT);196 dc->color=m->attr>>4;197 } else198 dc->color=m->attr&15;199 GrPrint(dc,x0,0,"%s",tmpme->name);200 y0=FONT_HEIGHT;201 tmpse=tmpme->sub;202 while (tmpse) {203 if (tmpse->checked)204 i=m->attr^0xFF;205 else206 i=m->attr;207 if (y0<=y1<y0+FONT_HEIGHT) {208 if (tmpse->msg_code==MSG_KEY_DOWN||209 tmpse->msg_code==MSG_KEY_DOWN_UP) {210 if (!tmpse->arg2)211 tmpse->arg2=Char2ScanCode(tmpse->arg1);212 st=ScanCode2KeyName(tmpse->arg2);213 }214 sys_cur_submenu_entry=cur_submenu=tmpse;215 dc->color=i&15;216 GrRect(dc,x0,y0,w,FONT_HEIGHT);217 dc->color=i>>4;218 GrPrint(dc,x0,y0,"%s",tmpse->name);219 if (st) {220 dc->color=i>>4;221 GrRect(dc,x0+w,y0-FONT_HEIGHT,222 (StrLen(st)+1)*FONT_WIDTH,FONT_HEIGHT*3);223 dc->color=i&15;224 GrPrint(dc,x0+w,y0,"%s",st);225 Free(st);226 }227 } else {228 dc->color=i>>4;229 GrRect(dc,x0,y0,w,FONT_HEIGHT);230 dc->color=i&15;231 GrPrint(dc,x0,y0,"%s",tmpse->name);232 }233 y0+=FONT_HEIGHT;234 tmpse=tmpse->next;235 }236 } else {237 dc->color=m->attr&15;238 GrPrint(dc,x0,0,"%s",tmpme->name);239 }240 x0+=w;241 tmpme=tmpme->next;242 }243 sys_cur_submenu_entry=cur_submenu;244}245 