]> git.lizzy.rs Git - dragonfireclient.git/blob - builtin/mainmenu.lua
filterlist api cleanup
[dragonfireclient.git] / builtin / mainmenu.lua
1 os.setlocale("C", "numeric")
2
3 local scriptpath = engine.get_scriptdir()
4
5 mt_color_grey  = "#AAAAAA"
6 mt_color_blue  = "#0000DD"
7 mt_color_green = "#00DD00"
8 mt_color_dark_green = "#003300"
9
10 dofile(scriptpath .. DIR_DELIM .. "filterlist.lua")
11 dofile(scriptpath .. DIR_DELIM .. "modmgr.lua")
12 dofile(scriptpath .. DIR_DELIM .. "modstore.lua")
13 dofile(scriptpath .. DIR_DELIM .. "gamemgr.lua")
14
15 local menu = {}
16 local tabbuilder = {}
17 local menubar = {}
18 local worldlist = nil
19
20 --------------------------------------------------------------------------------
21 function render_favourite(spec,render_details)
22         local text = ""
23         
24         if spec.name ~= nil then
25                 text = text .. fs_escape_string(spec.name:trim())
26                 
27 --              if spec.description ~= nil and
28 --                      fs_escape_string(spec.description):trim() ~= "" then
29 --                      text = text .. " (" .. fs_escape_string(spec.description) .. ")"
30 --              end
31         else
32                 if spec.address ~= nil then
33                         text = text .. spec.address:trim()
34                 end
35         end
36         
37         if spec.port ~= nil and
38                 spec.port ~= 30000 then
39                 
40                 text = text .. ":" .. spec.port
41         end
42         
43         if not render_details then
44                 return text
45         end
46         
47         local details = ""
48         if spec.password == true then
49                 details = details .. "*"
50         else
51                 details = details .. "_"
52         end
53         
54         if spec.creative then
55                 details = details .. "C"
56         else
57                 details = details .. "_"
58         end
59         
60         if spec.damage then
61                 details = details .. "D"
62         else
63                 details = details .. "_"
64         end
65         
66         if spec.pvp then
67                 details = details .. "P"
68         else
69                 details = details .. "_"
70         end
71         details = details .. "  "
72         
73         return fs_escape_string(details) .. text
74 end
75
76 --------------------------------------------------------------------------------
77 os.tempfolder = function()
78         local filetocheck = os.tmpname()
79         os.remove(filetocheck)
80         
81         local randname = "MTTempModFolder_" .. math.random(0,10000)
82         if DIR_DELIM == "\\" then
83                 local tempfolder = os.getenv("TEMP")
84                 return tempfolder .. filetocheck
85         else
86                 local backstring = filetocheck:reverse()
87                 return filetocheck:sub(0,filetocheck:len()-backstring:find(DIR_DELIM)+1) ..randname
88         end
89
90 end
91
92 --------------------------------------------------------------------------------
93 function cleanup_path(temppath)
94         
95         local parts = temppath:split("-")
96         temppath = ""   
97         for i=1,#parts,1 do
98                 if temppath ~= "" then
99                         temppath = temppath .. "_"
100                 end
101                 temppath = temppath .. parts[i]
102         end
103         
104         parts = temppath:split(".")
105         temppath = ""   
106         for i=1,#parts,1 do
107                 if temppath ~= "" then
108                         temppath = temppath .. "_"
109                 end
110                 temppath = temppath .. parts[i]
111         end
112         
113         parts = temppath:split("'")
114         temppath = ""   
115         for i=1,#parts,1 do
116                 if temppath ~= "" then
117                         temppath = temppath .. ""
118                 end
119                 temppath = temppath .. parts[i]
120         end
121         
122         parts = temppath:split(" ")
123         temppath = ""   
124         for i=1,#parts,1 do
125                 if temppath ~= "" then
126                         temppath = temppath
127                 end
128                 temppath = temppath .. parts[i]
129         end
130         
131         return temppath
132 end
133
134 --------------------------------------------------------------------------------
135
136 function menu.set_texture(identifier,gamedetails)
137         local texture_set = false
138         if menu.texturepack ~= nil and gamedetails ~= nil then
139                 local path = menu.basetexturedir .. 
140                                                 gamedetails.id .. "_menu_" .. identifier .. ".png"
141                 
142                 if engine.set_background(identifier,path) then
143                         texture_set = true
144                 end
145         end
146         
147         if not texture_set and gamedetails ~= nil then
148                 local path = gamedetails.path .. DIR_DELIM .."menu" .. 
149                                                                          DIR_DELIM .. identifier .. ".png"
150                 if engine.set_background(identifier,path) then
151                         texture_set = true
152                 end
153         end
154         
155         if not texture_set then
156                 local path = menu.basetexturedir .. DIR_DELIM .."menu_" .. 
157                                                                                 identifier .. ".png"
158                 if engine.set_background(identifier,path) then
159                         texture_set = true
160                 end
161         end
162         
163         if not texture_set then
164                 local path = menu.defaulttexturedir .. DIR_DELIM .."menu_" .. 
165                                                                                 identifier .. ".png"
166                 engine.set_background(identifier,path)
167         end
168 end
169
170 --------------------------------------------------------------------------------
171 function menu.update_gametype()
172         
173         
174         
175         if (menu.game_last_check == nil or
176                 menu.game_last_check ~= menu.last_game) and
177                 tabbuilder.current_tab == "singleplayer" then
178                 
179                 local gamedetails = menu.lastgame()
180                 engine.set_topleft_text(gamedetails.name)
181                 filterlist.set_filtercriteria(worldlist,gamedetails.id)
182                 
183                 --background
184                 local background_set = false
185                 if menu.texturepack ~= nil then
186                         local path_background_texture = menu.basetexturedir .. 
187                                                                                 gamedetails.id .. "_menu_background.png"
188                         
189                         if engine.set_background("background",path_background_texture) then
190                                 background_set = true
191                                 engine.set_clouds(false)
192                         end
193                 end
194                 
195                 if not background_set then
196                         local path_background_texture = gamedetails.path .. DIR_DELIM .."menu" .. 
197                                                                                  DIR_DELIM .. "background.png"
198                         if engine.set_background("background",path_background_texture) then
199                                 background_set = true
200                                 engine.set_clouds(false)
201                         end
202                 end
203                 
204                 if not background_set then
205                         engine.set_clouds(true)
206                 end
207                 
208                 menu.set_texture("overlay",gamedetails)
209                 menu.set_texture("header",gamedetails)
210                 menu.set_texture("footer",gamedetails)
211                 
212                 menu.game_last_check = menu.last_game
213         else
214                 if menu.game_last_check ~= menu.last_game then
215                         menu.game_last_check = menu.last_game
216                         menu.reset_gametype()
217                 end
218         end
219 end
220
221 --------------------------------------------------------------------------------
222 function menu.reset_gametype()
223         filterlist.set_filtercriteria(worldlist,nil)
224         menu.game_last_check = nil
225         
226         local path_background_texture = menu.basetexturedir .. "menu_background.png"
227                         
228         if engine.set_background("background",path_background_texture) then
229                 background_set = true
230                 engine.set_clouds(false)
231         else
232                 engine.set_clouds(true)
233         end 
234
235         menu.set_texture("overlay",nil)
236         menu.set_texture("header",nil)
237         menu.set_texture("footer",nil)
238         engine.set_topleft_text("")
239 end
240
241 --------------------------------------------------------------------------------
242 function get_last_folder(text,count)
243         local parts = text:split(DIR_DELIM)
244         
245         if count == nil then
246                 return parts[#parts]
247         end
248         
249         local retval = ""
250         for i=1,count,1 do
251                 retval = retval .. parts[#parts - (count-i)] .. DIR_DELIM
252         end
253         
254         return retval
255 end
256
257 --------------------------------------------------------------------------------
258 function init_globals()
259         --init gamedata
260         gamedata.worldindex = 0
261         
262         worldlist = filterlist.create(
263                                         engine.get_worlds,
264                                         compare_worlds,
265                                         function(element,uid)
266                                                 if element.name == uid then
267                                                         return true
268                                                 end
269                                                 return false
270                                         end, --unique id compare fct
271                                         function(element,gameid)
272                                                 if element.gameid == gameid then
273                                                         return true
274                                                 end
275                                                 return false
276                                         end --filter fct
277                                         )
278                                         
279         filterlist.add_sort_mechanism(worldlist,"alphabetic",sort_worlds_alphabetic)
280         filterlist.set_sortmode(worldlist,"alphabetic")
281                                         
282 end
283
284 --------------------------------------------------------------------------------
285 function identify_filetype(name)
286
287         if name:sub(-3):lower() == "zip" then
288                 return {
289                                 name = name,
290                                 type = "zip"
291                                 }
292         end
293         
294         if name:sub(-6):lower() == "tar.gz" or
295                 name:sub(-3):lower() == "tgz"then
296                 return {
297                                 name = name,
298                                 type = "tgz"
299                                 }
300         end
301         
302         if name:sub(-6):lower() == "tar.bz2" then
303                 return {
304                                 name = name,
305                                 type = "tbz"
306                                 }
307         end
308         
309         if name:sub(-2):lower() == "7z" then
310                 return {
311                                 name = name,
312                                 type = "7z"
313                                 }
314         end
315
316         return {
317                 name = name,
318                 type = "ukn"
319         }
320 end
321
322 --------------------------------------------------------------------------------
323 function update_menu()
324
325         local formspec = "size[12,5.2]"
326         
327         -- handle errors
328         if gamedata.errormessage ~= nil then
329                 formspec = formspec ..
330                         "field[1,2;10,2;;ERROR: " ..
331                         gamedata.errormessage .. 
332                         ";]"..
333                         "button[4.5,4.2;3,0.5;btn_error_confirm;Ok]"
334         else
335                 formspec = formspec .. tabbuilder.gettab()
336         end
337
338         engine.update_formspec(formspec)
339 end
340
341 --------------------------------------------------------------------------------
342 function menu.render_world_list()
343         local retval = ""
344         
345         local current_worldlist = filterlist.get_list(worldlist)
346         
347         for i,v in ipairs(current_worldlist) do
348                 if retval ~= "" then
349                         retval = retval ..","
350                 end
351                 
352                 retval = retval .. v.name .. 
353                                         " \\[" .. v.gameid .. "\\]"
354         end
355
356         return retval
357 end
358
359 --------------------------------------------------------------------------------
360 function menu.init()
361         --init menu data
362         gamemgr.update_gamelist()
363         
364         menu.last_game  = tonumber(engine.setting_get("main_menu_last_game_idx"))
365         
366         if type(menu.last_game) ~= "number" then
367                 menu.last_game = 1
368         end
369
370         if engine.setting_getbool("public_serverlist") then
371                 menu.favorites = engine.get_favorites("online")
372         else
373                 menu.favorites = engine.get_favorites("local")
374         end
375         
376         
377         menu.defaulttexturedir = engine.get_gamepath() .. DIR_DELIM .. ".." ..
378                                                 DIR_DELIM .. "textures" .. DIR_DELIM .. "base" .. 
379                                                 DIR_DELIM .. "pack" .. DIR_DELIM
380         menu.basetexturedir = menu.defaulttexturedir
381         
382         menu.texturepack = engine.setting_get("texture_path")
383         
384         if menu.texturepack ~= nil then
385                 menu.basetexturedir = menu.texturepack .. DIR_DELIM
386         end
387 end
388
389 --------------------------------------------------------------------------------
390 function menu.lastgame()
391         if menu.last_game > 0 and menu.last_game <= #gamemgr.games then
392                 return gamemgr.games[menu.last_game]
393         end
394         
395         if #gamemgr.games >= 1 then
396                 menu.last_game = 1
397                 return gamemgr.games[menu.last_game]
398         end
399         
400         --error case!!
401         return nil
402 end
403
404 --------------------------------------------------------------------------------
405 function menu.update_last_game()
406
407         local current_world = filterlist.get_raw_element(worldlist,
408                                                         engine.setting_get("mainmenu_last_selected_world")
409                                                         )
410                                                         
411         if current_world == nil then
412                 return
413         end
414                 
415         for i=1,#gamemgr.games,1 do             
416                 if gamemgr.games[i].id == current_world.gameid then
417                         menu.last_game = i
418                         engine.setting_set("main_menu_last_game_idx",menu.last_game)
419                         break
420                 end
421         end
422 end
423
424 --------------------------------------------------------------------------------
425 function menu.handle_key_up_down(fields,textlist,settingname)
426
427         if fields["key_up"] then
428                 local oldidx = engine.get_textlist_index(textlist)
429                 
430                 if oldidx > 1 then
431                         local newidx = oldidx -1
432                         engine.setting_set(settingname,
433                                 filterlist.get_raw_index(worldlist,newidx))
434                 end
435         end
436         
437         if fields["key_down"] then
438                 local oldidx = engine.get_textlist_index(textlist)
439                 
440                 if oldidx < filterlist.size(worldlist) then
441                         local newidx = oldidx + 1
442                         engine.setting_set(settingname,
443                                 filterlist.get_raw_index(worldlist,newidx))
444                 end
445         end
446 end
447
448
449 --------------------------------------------------------------------------------
450 function menubar.handle_buttons(fields)
451         for i=1,#menubar.buttons,1 do
452                 if fields[menubar.buttons[i].btn_name] ~= nil then
453                         menu.last_game = menubar.buttons[i].index
454                         engine.setting_set("main_menu_last_game_idx",menu.last_game)
455                         menu.update_gametype()
456                 end
457         end
458 end
459
460 --------------------------------------------------------------------------------
461 function menubar.refresh()
462         menubar.formspec = "box[-0.3,5.625;12.4,1.3;000000]" ..
463                                            "box[-0.3,5.6;12.4,0.05;FFFFFF]"
464         menubar.buttons = {}
465
466         local button_base = -0.25
467         
468         local maxbuttons = #gamemgr.games
469         
470         if maxbuttons > 10 then
471                 maxbuttons = 10
472         end
473         
474         for i=1,maxbuttons,1 do
475
476                 local btn_name = "menubar_btn_" .. gamemgr.games[i].id
477                 local buttonpos = button_base + (i-1) * 1.245
478                 if gamemgr.games[i].menuicon_path ~= nil and
479                         gamemgr.games[i].menuicon_path ~= "" then
480
481                         menubar.formspec = menubar.formspec ..
482                                 "image_button[" .. buttonpos ..  ",5.7;1.3,1.3;"  ..
483                                 gamemgr.games[i].menuicon_path .. ";" .. btn_name .. ";;true;false]"
484                 else
485                 
486                         local part1 = gamemgr.games[i].id:sub(1,5)
487                         local part2 = gamemgr.games[i].id:sub(6,10)
488                         local part3 = gamemgr.games[i].id:sub(11)
489                         
490                         local text = part1 .. "\n" .. part2
491                         if part3 ~= nil and
492                                 part3 ~= "" then
493                                 text = text .. "\n" .. part3
494                         end
495                         menubar.formspec = menubar.formspec ..
496                                 "image_button[" .. buttonpos ..  ",5.7;1.3,1.3;;" ..btn_name ..
497                                 ";" .. text .. ";true;true]"
498                 end
499                 
500                 local toadd = {
501                         btn_name = btn_name,
502                         index = i,
503                 }
504                 
505                 table.insert(menubar.buttons,toadd)
506         end
507 end
508
509 --------------------------------------------------------------------------------
510 function tabbuilder.dialog_create_world()
511         local mapgens = {"v6", "v7", "indev", "singlenode", "math"}
512
513         local current_mg = engine.setting_get("mg_name")
514
515         local mglist = ""
516         local selindex = 1
517         local i = 1
518         for k,v in pairs(mapgens) do
519                 if current_mg == v then
520                         selindex = i
521                 end
522                 i = i + 1
523                 mglist = mglist .. v .. ","
524         end
525         mglist = mglist:sub(1, -2)
526
527         local retval = 
528                 "label[2,0;World name]"..
529                 "label[2,1;Mapgen]"..
530                 "field[4.5,0.4;6,0.5;te_world_name;;]" ..
531                 "label[2,2;Game]"..
532                 "button[5,4.5;2.6,0.5;world_create_confirm;Create]" ..
533                 "button[7.5,4.5;2.8,0.5;world_create_cancel;Cancel]" ..
534                 "dropdown[4.2,1;6.3;dd_mapgen;" .. mglist .. ";" .. selindex .. "]" ..
535                 "textlist[4.2,1.9;5.8,2.3;games;" ..
536                 gamemgr.gamelist() ..
537                 ";" .. menu.last_game .. ";true]"
538
539         return retval
540 end
541
542 --------------------------------------------------------------------------------
543 function tabbuilder.dialog_delete_world()
544         return  "label[2,2;Delete World \"" .. filterlist.get_raw_list(worldlist)[menu.world_to_del].name .. "\"?]"..
545                         "button[3.5,4.2;2.6,0.5;world_delete_confirm;Yes]" ..
546                         "button[6,4.2;2.8,0.5;world_delete_cancel;No]"
547 end
548
549 --------------------------------------------------------------------------------
550 function tabbuilder.gettab()
551         local retval = ""
552         
553         if tabbuilder.show_buttons then
554                 retval = retval .. tabbuilder.tab_header()
555         end
556
557         if tabbuilder.current_tab == "singleplayer" then
558                 retval = retval .. tabbuilder.tab_singleplayer()
559         end
560         
561         if tabbuilder.current_tab == "multiplayer" then
562                 retval = retval .. tabbuilder.tab_multiplayer()
563         end
564
565         if tabbuilder.current_tab == "server" then
566                 retval = retval .. tabbuilder.tab_server()
567         end
568         
569         if tabbuilder.current_tab == "settings" then
570                 retval = retval .. tabbuilder.tab_settings()
571         end
572         
573         if tabbuilder.current_tab == "credits" then
574                 retval = retval .. tabbuilder.tab_credits()
575         end
576         
577         if tabbuilder.current_tab == "dialog_create_world" then
578                 retval = retval .. tabbuilder.dialog_create_world()
579         end
580         
581         if tabbuilder.current_tab == "dialog_delete_world" then
582                 retval = retval .. tabbuilder.dialog_delete_world()
583         end
584         
585         retval = retval .. modmgr.gettab(tabbuilder.current_tab)
586         retval = retval .. gamemgr.gettab(tabbuilder.current_tab)
587         retval = retval .. modstore.gettab(tabbuilder.current_tab)
588
589         return retval
590 end
591
592 --------------------------------------------------------------------------------
593 function tabbuilder.handle_create_world_buttons(fields)
594         
595         if fields["world_create_confirm"] or
596                 fields["key_enter"] then
597                 
598                 local worldname = fields["te_world_name"]
599                 local gameindex = engine.get_textlist_index("games")
600                 
601                 if gameindex > 0 and
602                         worldname ~= "" then
603                         
604                         local message = nil
605                         
606                         if not filterlist.uid_exists(worldlist,worldname) then
607                                 engine.setting_set("mg_name",fields["dd_mapgen"])
608                                 message = engine.create_world(worldname,gameindex)
609                         else
610                                 message = "A world named \"" .. worldname .. "\" already exists"
611                         end
612                         
613                         if message ~= nil then
614                                 gamedata.errormessage = message
615                         else
616                                 menu.last_game = gameindex
617                                 engine.setting_set("main_menu_last_game_idx",gameindex)
618                                 
619                                 filterlist.refresh(worldlist)
620                                 engine.setting_set("mainmenu_last_selected_world",
621                                                                         filterlist.raw_index_by_uid(worldlist,worldname))
622                         end
623                 else
624                         gamedata.errormessage = "No worldname given or no game selected"
625                 end
626         end
627         
628         if fields["games"] then
629                 tabbuilder.skipformupdate = true
630                 return
631         end
632         
633         --close dialog
634         tabbuilder.is_dialog = false
635         tabbuilder.show_buttons = true
636         tabbuilder.current_tab = engine.setting_get("main_menu_tab")
637 end
638
639 --------------------------------------------------------------------------------
640 function tabbuilder.handle_delete_world_buttons(fields)
641         
642         if fields["world_delete_confirm"] then
643                 if menu.world_to_del > 0 and 
644                         menu.world_to_del <= #filterlist.get_raw_list(worldlist) then
645                         engine.delete_world(menu.world_to_del)
646                         menu.world_to_del = 0
647                         filterlist.refresh(worldlist)
648                 end
649         end
650         
651         tabbuilder.is_dialog = false
652         tabbuilder.show_buttons = true
653         tabbuilder.current_tab = engine.setting_get("main_menu_tab")
654 end
655
656 --------------------------------------------------------------------------------
657 function tabbuilder.handle_multiplayer_buttons(fields)
658         
659         if fields["te_name"] ~= nil then
660                 gamedata.playername = fields["te_name"]
661                 engine.setting_set("name", fields["te_name"])
662         end
663         
664         if fields["favourites"] ~= nil then
665                 local event = explode_textlist_event(fields["favourites"])
666                 if event.typ == "DCL" then
667                         gamedata.address = menu.favorites[event.index].address
668                         gamedata.port = menu.favorites[event.index].port
669                         gamedata.playername             = fields["te_name"]
670                         if fields["te_pwd"] ~= nil then
671                                 gamedata.password               = fields["te_pwd"]
672                         end
673                         gamedata.selected_world = 0
674                         
675                         if menu.favorites ~= nil then
676                                 gamedata.servername = menu.favorites[event.index].name
677                                 gamedata.serverdescription = menu.favorites[event.index].description
678                         end
679                         
680                         if gamedata.address ~= nil and
681                                 gamedata.port ~= nil then
682                                 
683                                 engine.start()
684                         end
685                 end
686                 
687                 if event.typ == "CHG" then
688                         local address = menu.favorites[event.index].address
689                         local port = menu.favorites[event.index].port
690                         
691                         if address ~= nil and
692                                 port ~= nil then
693                                 engine.setting_set("address",address)
694                                 engine.setting_set("port",port)
695                         end
696                         
697                         menu.fav_selected = event.index
698                 end
699                 return
700         end
701         
702         if fields["key_up"] ~= nil or
703                 fields["key_down"] ~= nil then
704                 
705                 local fav_idx = engine.get_textlist_index("favourites")
706                 
707                 if fields["key_up"] ~= nil and fav_idx > 1 then
708                         fav_idx = fav_idx -1
709                 else if fields["key_down"] and fav_idx < #menu.favorites then
710                         fav_idx = fav_idx +1
711                 end end
712                 
713                 local address = menu.favorites[fav_idx].address
714                 local port = menu.favorites[fav_idx].port
715                 
716                 if address ~= nil and
717                         port ~= nil then
718                         engine.setting_set("address",address)
719                         engine.setting_set("port",port)
720                 end
721                 
722                 menu.fav_selected = fav_idx
723                 return
724         end
725         
726         if fields["cb_public_serverlist"] ~= nil then
727                 engine.setting_setbool("public_serverlist",
728                         tabbuilder.tobool(fields["cb_public_serverlist"]))
729                         
730                 if engine.setting_getbool("public_serverlist") then
731                         menu.favorites = engine.get_favorites("online")
732                 else
733                         menu.favorites = engine.get_favorites("local")
734                 end
735                 menu.fav_selected = nil
736                 return
737         end
738
739         if fields["btn_delete_favorite"] ~= nil then
740                 local current_favourite = engine.get_textlist_index("favourites")
741                 engine.delete_favorite(current_favourite)
742                 menu.favorites = engine.get_favorites()
743                 menu.fav_selected = nil
744                 
745                 engine.setting_set("address","")
746                 engine.setting_get("port","")
747                 
748                 return
749         end
750
751         if fields["btn_mp_connect"] ~= nil or
752                 fields["key_enter"] then
753                 
754                 gamedata.playername             = fields["te_name"]
755                 gamedata.password               = fields["te_pwd"]
756                 gamedata.address                = fields["te_address"]
757                 gamedata.port                   = fields["te_port"]
758                 
759                 local fav_idx = engine.get_textlist_index("favourites")
760                 
761                 if fav_idx > 0 and fav_idx <= #menu.favorites and
762                         menu.favorites[fav_idx].address == fields["te_address"] and
763                         menu.favorites[fav_idx].port == fields["te_port"] then
764                         
765                         gamedata.servername                     = menu.favorites[fav_idx].name
766                         gamedata.serverdescription      = menu.favorites[fav_idx].description
767                 else
768                         gamedata.servername = ""
769                         gamedata.serverdescription = ""
770                 end
771
772                 gamedata.selected_world = 0
773                 
774                 engine.start()
775                 return
776         end
777 end
778
779 --------------------------------------------------------------------------------
780 function tabbuilder.handle_server_buttons(fields)
781
782         local world_doubleclick = false
783
784         if fields["srv_worlds"] ~= nil then
785                 local event = explode_textlist_event(fields["srv_worlds"])
786                 
787                 if event.typ == "DCL" then
788                         world_doubleclick = true
789                 end
790                 if event.typ == "CHG" then
791                         engine.setting_set("mainmenu_last_selected_world",
792                                 filterlist.get_raw_index(worldlist,engine.get_textlist_index("srv_worlds")))
793                 end
794         end
795         
796         menu.handle_key_up_down(fields,"srv_worlds","mainmenu_last_selected_world")
797         
798         if fields["cb_creative_mode"] then
799                 engine.setting_setbool("creative_mode",tabbuilder.tobool(fields["cb_creative_mode"]))
800         end
801         
802         if fields["cb_enable_damage"] then
803                 engine.setting_setbool("enable_damage",tabbuilder.tobool(fields["cb_enable_damage"]))
804         end
805
806         if fields["cb_server_announce"] then
807                 engine.setting_setbool("server_announce",tabbuilder.tobool(fields["cb_server_announce"]))
808         end
809         
810         if fields["start_server"] ~= nil or
811                 world_doubleclick or
812                 fields["key_enter"] then
813                 local selected = engine.get_textlist_index("srv_worlds")
814                 if selected > 0 then
815                         gamedata.playername             = fields["te_playername"]
816                         gamedata.password               = fields["te_passwd"]
817                         gamedata.port                   = fields["te_serverport"]
818                         gamedata.address                = ""
819                         gamedata.selected_world = filterlist.get_raw_index(worldlist,selected)
820                         
821                         menu.update_last_game(gamedata.selected_world)
822                         engine.start()
823                 end
824         end
825         
826         if fields["world_create"] ~= nil then
827                 tabbuilder.current_tab = "dialog_create_world"
828                 tabbuilder.is_dialog = true
829                 tabbuilder.show_buttons = false
830         end
831         
832         if fields["world_delete"] ~= nil then
833                 local selected = engine.get_textlist_index("srv_worlds")
834                 if selected > 0 and
835                         selected <= filterlist.size(worldlist) then
836                         local world = filterlist.get_list(worldlist)[selected]
837                         if world ~= nil and
838                                 world.name ~= nil and
839                                 world.name ~= "" then
840                                 menu.world_to_del = filterlist.get_raw_index(worldlist,selected)
841                                 tabbuilder.current_tab = "dialog_delete_world"
842                                 tabbuilder.is_dialog = true
843                                 tabbuilder.show_buttons = false
844                         else
845                                 menu.world_to_del = 0
846                         end
847                 end
848         end
849         
850         if fields["world_configure"] ~= nil then
851                 selected = engine.get_textlist_index("srv_worlds")
852                 if selected > 0 then
853                         modmgr.world_config_selected_world = filterlist.get_raw_index(worldlist,selected)
854                         if modmgr.init_worldconfig() then
855                                 tabbuilder.current_tab = "dialog_configure_world"
856                                 tabbuilder.is_dialog = true
857                                 tabbuilder.show_buttons = false
858                         end
859                 end
860         end
861 end
862
863 --------------------------------------------------------------------------------
864 function tabbuilder.tobool(text)
865         if text == "true" then
866                 return true
867         else
868                 return false
869         end
870 end
871
872 --------------------------------------------------------------------------------
873 function tabbuilder.handle_settings_buttons(fields)
874         if fields["cb_fancy_trees"] then
875                 engine.setting_setbool("new_style_leaves",tabbuilder.tobool(fields["cb_fancy_trees"]))
876         end
877                 
878         if fields["cb_smooth_lighting"] then
879                 engine.setting_setbool("smooth_lighting",tabbuilder.tobool(fields["cb_smooth_lighting"]))
880         end
881         if fields["cb_3d_clouds"] then
882                 engine.setting_setbool("enable_3d_clouds",tabbuilder.tobool(fields["cb_3d_clouds"]))
883         end
884         if fields["cb_opaque_water"] then
885                 engine.setting_setbool("opaque_water",tabbuilder.tobool(fields["cb_opaque_water"]))
886         end
887                         
888         if fields["cb_mipmapping"] then
889                 engine.setting_setbool("mip_map",tabbuilder.tobool(fields["cb_mipmapping"]))
890         end
891         if fields["cb_anisotrophic"] then
892                 engine.setting_setbool("anisotropic_filter",tabbuilder.tobool(fields["cb_anisotrophic"]))
893         end
894         if fields["cb_bilinear"] then
895                 engine.setting_setbool("bilinear_filter",tabbuilder.tobool(fields["cb_bilinear"]))
896         end
897         if fields["cb_trilinear"] then
898                 engine.setting_setbool("trilinear_filter",tabbuilder.tobool(fields["cb_trilinear"]))
899         end
900                         
901         if fields["cb_shaders"] then
902                 engine.setting_setbool("enable_shaders",tabbuilder.tobool(fields["cb_shaders"]))
903         end
904         if fields["cb_pre_ivis"] then
905                 engine.setting_setbool("preload_item_visuals",tabbuilder.tobool(fields["cb_pre_ivis"]))
906         end
907         if fields["cb_particles"] then
908                 engine.setting_setbool("enable_particles",tabbuilder.tobool(fields["cb_particles"]))
909         end
910         if fields["cb_finite_liquid"] then
911                 engine.setting_setbool("liquid_finite",tabbuilder.tobool(fields["cb_finite_liquid"]))
912         end
913
914         if fields["btn_change_keys"] ~= nil then
915                 engine.show_keys_menu()
916         end
917 end
918
919 --------------------------------------------------------------------------------
920 function tabbuilder.handle_singleplayer_buttons(fields)
921
922         local world_doubleclick = false
923
924         if fields["sp_worlds"] ~= nil then
925                 local event = explode_textlist_event(fields["sp_worlds"])
926                 
927                 if event.typ == "DCL" then
928                         world_doubleclick = true
929                 end
930                 
931                 if event.typ == "CHG" then
932                         engine.setting_set("mainmenu_last_selected_world",
933                                 filterlist.get_raw_index(worldlist,engine.get_textlist_index("sp_worlds")))
934                 end
935         end
936         
937         menu.handle_key_up_down(fields,"sp_worlds","mainmenu_last_selected_world")
938         
939         if fields["cb_creative_mode"] then
940                 engine.setting_setbool("creative_mode",tabbuilder.tobool(fields["cb_creative_mode"]))
941         end
942         
943         if fields["cb_enable_damage"] then
944                 engine.setting_setbool("enable_damage",tabbuilder.tobool(fields["cb_enable_damage"]))
945         end
946
947         if fields["play"] ~= nil or
948                 world_doubleclick or
949                 fields["key_enter"] then
950                 local selected = engine.get_textlist_index("sp_worlds")
951                 if selected > 0 then
952                         gamedata.selected_world = filterlist.get_raw_index(worldlist,selected)
953                         gamedata.singleplayer   = true
954                         
955                         menu.update_last_game(gamedata.selected_world)
956                         
957                         engine.start()
958                 end
959         end
960         
961         if fields["world_create"] ~= nil then
962                 tabbuilder.current_tab = "dialog_create_world"
963                 tabbuilder.is_dialog = true
964                 tabbuilder.show_buttons = false
965         end
966         
967         if fields["world_delete"] ~= nil then
968                 local selected = engine.get_textlist_index("sp_worlds")
969                 if selected > 0 and
970                         selected <= filterlist.size(worldlist) then
971                         local world = filterlist.get_list(worldlist)[selected]
972                         if world ~= nil and
973                                 world.name ~= nil and
974                                 world.name ~= "" then
975                                 menu.world_to_del = filterlist.get_raw_index(worldlist,selected)
976                                 tabbuilder.current_tab = "dialog_delete_world"
977                                 tabbuilder.is_dialog = true
978                                 tabbuilder.show_buttons = false
979                         else
980                                 menu.world_to_del = 0
981                         end
982                 end
983         end
984         
985         if fields["world_configure"] ~= nil then
986                 selected = engine.get_textlist_index("sp_worlds")
987                 if selected > 0 then
988                         modmgr.world_config_selected_world = filterlist.get_raw_index(worldlist,selected)
989                         if modmgr.init_worldconfig() then
990                                 tabbuilder.current_tab = "dialog_configure_world"
991                                 tabbuilder.is_dialog = true
992                                 tabbuilder.show_buttons = false
993                         end
994                 end
995         end
996 end
997
998 --------------------------------------------------------------------------------
999 function tabbuilder.tab_header()
1000
1001         if tabbuilder.last_tab_index == nil then
1002                 tabbuilder.last_tab_index = 1
1003         end
1004         
1005         local toadd = ""
1006         
1007         for i=1,#tabbuilder.current_buttons,1 do
1008                 
1009                 if toadd ~= "" then
1010                         toadd = toadd .. ","
1011                 end
1012                 
1013                 toadd = toadd .. tabbuilder.current_buttons[i].caption
1014         end
1015         return "tabheader[-0.3,-0.99;main_tab;" .. toadd ..";" .. tabbuilder.last_tab_index .. ";true;false]"
1016 end
1017
1018 --------------------------------------------------------------------------------
1019 function tabbuilder.handle_tab_buttons(fields)
1020
1021         if fields["main_tab"] then
1022                 local index = tonumber(fields["main_tab"])
1023                 tabbuilder.last_tab_index = index
1024                 tabbuilder.current_tab = tabbuilder.current_buttons[index].name
1025                 
1026                 engine.setting_set("main_menu_tab",tabbuilder.current_tab)
1027         end
1028         
1029         --handle tab changes
1030         if tabbuilder.current_tab ~= tabbuilder.old_tab then
1031                 if tabbuilder.current_tab ~= "singleplayer" then
1032                         menu.reset_gametype()
1033                 end
1034         end
1035         
1036         if tabbuilder.current_tab == "singleplayer" then
1037                 menu.update_gametype()
1038         end
1039         
1040         tabbuilder.old_tab = tabbuilder.current_tab
1041 end
1042
1043 --------------------------------------------------------------------------------
1044 function tabbuilder.init()
1045         tabbuilder.current_tab = engine.setting_get("main_menu_tab")
1046         
1047         if tabbuilder.current_tab == nil or
1048                 tabbuilder.current_tab == "" then
1049                 tabbuilder.current_tab = "singleplayer"
1050                 engine.setting_set("main_menu_tab",tabbuilder.current_tab)
1051         end
1052         
1053         
1054         --initialize tab buttons
1055         tabbuilder.last_tab = nil
1056         tabbuilder.show_buttons = true
1057         
1058         tabbuilder.current_buttons = {}
1059         table.insert(tabbuilder.current_buttons,{name="singleplayer", caption="Singleplayer"})
1060         table.insert(tabbuilder.current_buttons,{name="multiplayer", caption="Client"})
1061         table.insert(tabbuilder.current_buttons,{name="server", caption="Server"})
1062         table.insert(tabbuilder.current_buttons,{name="settings", caption="Settings"})
1063         
1064         if engine.setting_getbool("main_menu_game_mgr") then
1065                 table.insert(tabbuilder.current_buttons,{name="game_mgr", caption="Games"})
1066         end
1067         
1068         if engine.setting_getbool("main_menu_mod_mgr") then
1069                 table.insert(tabbuilder.current_buttons,{name="mod_mgr", caption="Mods"})
1070         end
1071         table.insert(tabbuilder.current_buttons,{name="credits", caption="Credits"})
1072         
1073         
1074         for i=1,#tabbuilder.current_buttons,1 do
1075                 if tabbuilder.current_buttons[i].name == tabbuilder.current_tab then
1076                         tabbuilder.last_tab_index = i
1077                 end
1078         end
1079         
1080         menu.update_gametype()
1081 end
1082
1083 --------------------------------------------------------------------------------
1084 function tabbuilder.tab_multiplayer()
1085
1086         local retval =
1087                 "vertlabel[0,-0.25;CLIENT]" ..
1088                 "label[1,-0.25;Favorites:]"..
1089                 "label[1,4.25;Address/Port]"..
1090                 "label[9,2.75;Name/Password]" ..
1091                 "field[1.25,5.25;5.5,0.5;te_address;;" ..engine.setting_get("address") .."]" ..
1092                 "field[6.75,5.25;2.25,0.5;te_port;;" ..engine.setting_get("port") .."]" ..
1093                 "checkbox[1,3.6;cb_public_serverlist;Public Serverlist;" ..
1094                 dump(engine.setting_getbool("public_serverlist")) .. "]"
1095                 
1096         if not engine.setting_getbool("public_serverlist") then
1097                 retval = retval .. 
1098                 "button[6.45,3.95;2.25,0.5;btn_delete_favorite;Delete]"
1099         end
1100         
1101         retval = retval ..
1102                 "button[9,4.95;2.5,0.5;btn_mp_connect;Connect]" ..
1103                 "field[9.3,3.75;2.5,0.5;te_name;;" ..engine.setting_get("name") .."]" ..
1104                 "pwdfield[9.3,4.5;2.5,0.5;te_pwd;]" ..
1105                 "textarea[9.3,0.25;2.5,2.75;;"
1106         if menu.fav_selected ~= nil and 
1107                 menu.favorites[menu.fav_selected].description ~= nil then
1108                 retval = retval .. 
1109                         fs_escape_string(menu.favorites[menu.fav_selected].description,true)
1110         end
1111         
1112         retval = retval .. 
1113                 ";]" ..
1114                 "textlist[1,0.35;7.5,3.35;favourites;"
1115
1116         local render_details = engine.setting_getbool("public_serverlist")
1117
1118         if #menu.favorites > 0 then
1119                 retval = retval .. render_favourite(menu.favorites[1],render_details)
1120                 
1121                 for i=2,#menu.favorites,1 do
1122                         retval = retval .. "," .. render_favourite(menu.favorites[i],render_details)
1123                 end
1124         end
1125
1126         if menu.fav_selected ~= nil then
1127                 retval = retval .. ";" .. menu.fav_selected .. "]"
1128         else
1129                 retval = retval .. ";0]"
1130         end
1131
1132         return retval
1133 end
1134
1135 --------------------------------------------------------------------------------
1136 function tabbuilder.tab_server()
1137
1138         local index = filterlist.get_current_index(worldlist,
1139                                 tonumber(engine.setting_get("mainmenu_last_selected_world"))
1140                                 )
1141         
1142         local retval = 
1143                 "button[4,4.15;2.6,0.5;world_delete;Delete]" ..
1144                 "button[6.5,4.15;2.8,0.5;world_create;New]" ..
1145                 "button[9.2,4.15;2.55,0.5;world_configure;Configure]" ..
1146                 "button[8.5,4.9;3.25,0.5;start_server;Start Game]" ..
1147                 "label[4,-0.25;Select World:]"..
1148                 "vertlabel[0,-0.25;START SERVER]" ..
1149                 "checkbox[0.5,0.25;cb_creative_mode;Creative Mode;" ..
1150                 dump(engine.setting_getbool("creative_mode")) .. "]"..
1151                 "checkbox[0.5,0.7;cb_enable_damage;Enable Damage;" ..
1152                 dump(engine.setting_getbool("enable_damage")) .. "]"..
1153                 "checkbox[0.5,1.15;cb_server_announce;Public;" ..
1154                 dump(engine.setting_getbool("server_announce")) .. "]"..
1155                 "field[0.8,3.2;3,0.5;te_playername;Name;" ..
1156                 engine.setting_get("name") .. "]" ..
1157                 "pwdfield[0.8,4.2;3,0.5;te_passwd;Password]" ..
1158                 "field[0.8,5.2;3,0.5;te_serverport;Server Port;30000]" ..
1159                 "textlist[4,0.25;7.5,3.7;srv_worlds;" ..
1160                 menu.render_world_list() ..
1161                 ";" .. index .. "]"
1162                 
1163         return retval
1164 end
1165
1166 --------------------------------------------------------------------------------
1167 function tabbuilder.tab_settings()
1168         return  "vertlabel[0,0;SETTINGS]" ..
1169                         "checkbox[1,0.75;cb_fancy_trees;Fancy trees;"           .. dump(engine.setting_getbool("new_style_leaves"))     .. "]"..
1170                         "checkbox[1,1.25;cb_smooth_lighting;Smooth Lighting;".. dump(engine.setting_getbool("smooth_lighting")) .. "]"..
1171                         "checkbox[1,1.75;cb_3d_clouds;3D Clouds;"                       .. dump(engine.setting_getbool("enable_3d_clouds"))     .. "]"..
1172                         "checkbox[1,2.25;cb_opaque_water;Opaque Water;"                 .. dump(engine.setting_getbool("opaque_water"))         .. "]"..
1173                         
1174                         "checkbox[4,0.75;cb_mipmapping;Mip-Mapping;"            .. dump(engine.setting_getbool("mip_map"))                      .. "]"..
1175                         "checkbox[4,1.25;cb_anisotrophic;Anisotropic Filtering;".. dump(engine.setting_getbool("anisotropic_filter"))   .. "]"..
1176                         "checkbox[4,1.75;cb_bilinear;Bi-Linear Filtering;"      .. dump(engine.setting_getbool("bilinear_filter"))      .. "]"..
1177                         "checkbox[4,2.25;cb_trilinear;Tri-Linear Filtering;"    .. dump(engine.setting_getbool("trilinear_filter"))     .. "]"..
1178                         
1179                         "checkbox[7.5,0.75;cb_shaders;Shaders;"                         .. dump(engine.setting_getbool("enable_shaders"))               .. "]"..
1180                         "checkbox[7.5,1.25;cb_pre_ivis;Preload item visuals;".. dump(engine.setting_getbool("preload_item_visuals"))    .. "]"..
1181                         "checkbox[7.5,1.75;cb_particles;Enable Particles;"      .. dump(engine.setting_getbool("enable_particles"))     .. "]"..
1182                         "checkbox[7.5,2.25;cb_finite_liquid;Finite Liquid;"     .. dump(engine.setting_getbool("liquid_finite"))                .. "]"..
1183                         
1184                         "button[1,3.75;2.25,0.5;btn_change_keys;Change keys]"
1185 end
1186
1187 --------------------------------------------------------------------------------
1188 function tabbuilder.tab_singleplayer()
1189         
1190         local index = filterlist.get_current_index(worldlist,
1191                                 tonumber(engine.setting_get("mainmenu_last_selected_world"))
1192                                 )
1193
1194         return  "button[4,4.15;2.6,0.5;world_delete;Delete]" ..
1195                         "button[6.5,4.15;2.8,0.5;world_create;New]" ..
1196                         "button[9.2,4.15;2.55,0.5;world_configure;Configure]" ..
1197                         "button[8.5,4.95;3.25,0.5;play;Play]" ..
1198                         "label[4,-0.25;Select World:]"..
1199                         "vertlabel[0,-0.25;SINGLE PLAYER]" ..
1200                         "checkbox[0.5,0.25;cb_creative_mode;Creative Mode;" ..
1201                         dump(engine.setting_getbool("creative_mode")) .. "]"..
1202                         "checkbox[0.5,0.7;cb_enable_damage;Enable Damage;" ..
1203                         dump(engine.setting_getbool("enable_damage")) .. "]"..
1204                         "textlist[4,0.25;7.5,3.7;sp_worlds;" ..
1205                         menu.render_world_list() ..
1206                         ";" .. index .. "]" ..
1207                         menubar.formspec
1208 end
1209
1210 --------------------------------------------------------------------------------
1211 function tabbuilder.tab_credits()
1212         return  "vertlabel[0,-0.5;CREDITS]" ..
1213                         "label[0.5,3;Minetest " .. engine.get_version() .. "]" ..
1214                         "label[0.5,3.3;http://minetest.net]" .. 
1215                         "image[0.5,1;" .. menu.defaulttexturedir .. "logo.png]" ..
1216                         "textlist[3.5,-0.25;8.5,5.8;list_credits;" ..
1217                         "#FFFF00Core Developers," ..
1218                         "Perttu Ahola (celeron55) <celeron55@gmail.com>,"..
1219                         "Ryan Kwolek (kwolekr) <kwolekr@minetest.net>,"..
1220                         "PilzAdam <pilzadam@minetest.net>," ..
1221                         "IIya Zhuravlev (thexyz) <xyz@minetest.net>,"..
1222                         "Lisa Milne (darkrose) <lisa@ltmnet.com>,"..
1223                         "Maciej Kasatkin (RealBadAngel) <mk@realbadangel.pl>,"..
1224                         "proller <proler@gmail.com>,"..
1225                         "sfan5 <sfan5@live.de>,"..
1226                         "kahrl <kahrl@gmx.net>,"..
1227                         ","..
1228                         "#FFFF00Active Contributors," ..
1229                         "sapier,"..
1230                         "Vanessa Ezekowitz (VanessaE) <vanessaezekowitz@gmail.com>,"..
1231                         "Jurgen Doser (doserj) <jurgen.doser@gmail.com>,"..
1232                         "Jeija <jeija@mesecons.net>,"..
1233                         "MirceaKitsune <mirceakitsune@gmail.com>,"..
1234                         "ShadowNinja,"..
1235                         "dannydark <the_skeleton_of_a_child@yahoo.co.uk>,"..
1236                         "0gb.us <0gb.us@0gb.us>,"..
1237                         "," ..
1238                         "#FFFF00Previous Contributors," ..
1239                         "Guiseppe Bilotta (Oblomov) <guiseppe.bilotta@gmail.com>,"..
1240                         "Jonathan Neuschafer <j.neuschaefer@gmx.net>,"..
1241                         "Nils Dagsson Moskopp (erlehmann) <nils@dieweltistgarnichtso.net>,"..
1242                         "Constantin Wenger (SpeedProg) <constantin.wenger@googlemail.com>,"..
1243                         "matttpt <matttpt@gmail.com>,"..
1244                         "JacobF <queatz@gmail.com>,"..
1245                         ";0;true]"
1246 end
1247
1248 --------------------------------------------------------------------------------
1249 function tabbuilder.checkretval(retval)
1250
1251         if retval ~= nil then
1252                 if retval.current_tab ~= nil then
1253                         tabbuilder.current_tab = retval.current_tab
1254                 end
1255                 
1256                 if retval.is_dialog ~= nil then
1257                         tabbuilder.is_dialog = retval.is_dialog
1258                 end
1259                 
1260                 if retval.show_buttons ~= nil then
1261                         tabbuilder.show_buttons = retval.show_buttons
1262                 end
1263                 
1264                 if retval.skipformupdate ~= nil then
1265                         tabbuilder.skipformupdate = retval.skipformupdate
1266                 end
1267         end
1268 end
1269
1270 --------------------------------------------------------------------------------
1271 --------------------------------------------------------------------------------
1272 -- initialize callbacks
1273 --------------------------------------------------------------------------------
1274 --------------------------------------------------------------------------------
1275 engine.button_handler = function(fields)
1276         --print("Buttonhandler: tab: " .. tabbuilder.current_tab .. " fields: " .. dump(fields))
1277         
1278         if fields["btn_error_confirm"] then
1279                 gamedata.errormessage = nil
1280         end
1281         
1282         local retval = modmgr.handle_buttons(tabbuilder.current_tab,fields)
1283         tabbuilder.checkretval(retval)
1284         
1285         retval = gamemgr.handle_buttons(tabbuilder.current_tab,fields)
1286         tabbuilder.checkretval(retval)
1287         
1288         retval = modstore.handle_buttons(tabbuilder.current_tab,fields)
1289         tabbuilder.checkretval(retval)
1290         
1291         if tabbuilder.current_tab == "dialog_create_world" then
1292                 tabbuilder.handle_create_world_buttons(fields)
1293         end
1294         
1295         if tabbuilder.current_tab == "dialog_delete_world" then
1296                 tabbuilder.handle_delete_world_buttons(fields)
1297         end
1298         
1299         if tabbuilder.current_tab == "singleplayer" then
1300                 tabbuilder.handle_singleplayer_buttons(fields)
1301         end
1302         
1303         if tabbuilder.current_tab == "multiplayer" then
1304                 tabbuilder.handle_multiplayer_buttons(fields)
1305         end
1306         
1307         if tabbuilder.current_tab == "settings" then
1308                 tabbuilder.handle_settings_buttons(fields)
1309         end
1310         
1311         if tabbuilder.current_tab == "server" then
1312                 tabbuilder.handle_server_buttons(fields)
1313         end
1314         
1315         --tab buttons
1316         tabbuilder.handle_tab_buttons(fields)
1317         
1318         --menubar buttons
1319         menubar.handle_buttons(fields)
1320         
1321         if not tabbuilder.skipformupdate then
1322                 --update menu
1323                 update_menu()
1324         else
1325                 tabbuilder.skipformupdate = false
1326         end
1327 end
1328
1329 --------------------------------------------------------------------------------
1330 engine.event_handler = function(event)
1331         if event == "MenuQuit" then
1332                 if tabbuilder.is_dialog then
1333                         tabbuilder.is_dialog = false
1334                         tabbuilder.show_buttons = true
1335                         tabbuilder.current_tab = engine.setting_get("main_menu_tab")
1336                         menu.update_gametype()
1337                         update_menu()
1338                 else
1339                         engine.close()
1340                 end
1341         end
1342 end
1343
1344 --------------------------------------------------------------------------------
1345 --------------------------------------------------------------------------------
1346 -- menu startup
1347 --------------------------------------------------------------------------------
1348 --------------------------------------------------------------------------------
1349 init_globals()
1350 menu.init()
1351 tabbuilder.init()
1352 menubar.refresh()
1353 modstore.init()
1354
1355 update_menu()