summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Wilgus <wilgus.william@gmail.com>2024-05-04 08:41:16 -0400
committerWilliam Wilgus <wilgus.william@gmail.com>2024-05-05 14:01:43 -0400
commitd7c541742f5e6ec07dbcc8e1346efde9d807437e (patch)
tree2c3325b652999bd9b2443eb96d8d32035d3c4c18
parentefcea6628024c5f6796c3850c3779801db4b6874 (diff)
downloadrockbox-d7c541742f5e6ec07dbcc8e1346efde9d807437e.tar.gz
rockbox-d7c541742f5e6ec07dbcc8e1346efde9d807437e.zip
Allow first level folders in plugin menu
add sorting directories as files move picross files to a hidden folder use directory for lua_scripts, sgt_puzzles make plugin browser able to handle 1st level directories Change-Id: I30852d71dc992c378d5790756e94f06f5a2e9bef
-rw-r--r--apps/filetree.c68
-rw-r--r--apps/plugins/CATEGORIES1
-rw-r--r--apps/plugins/SOURCES1
-rw-r--r--apps/plugins/lua/include_lua/dbgettags.lua119
-rwxr-xr-xapps/plugins/lua/include_lua/filebrowse.lua241
-rwxr-xr-xapps/plugins/lua/include_lua/fileviewers.lua468
-rw-r--r--apps/plugins/lua/lua.make12
-rw-r--r--apps/plugins/lua_scripts/lua_scripts.lua172
-rw-r--r--apps/plugins/lua_scripts/lua_scripts.make4
-rw-r--r--apps/plugins/picross.lua8
-rw-r--r--apps/plugins/picross/picross.make4
-rw-r--r--apps/settings.h2
-rw-r--r--apps/tree.c9
-rwxr-xr-xtools/buildzip.pl28
14 files changed, 1079 insertions, 58 deletions
diff --git a/apps/filetree.c b/apps/filetree.c
index b5f5dece5a..594a0bd6f1 100644
--- a/apps/filetree.c
+++ b/apps/filetree.c
@@ -224,7 +224,11 @@ static int compare(const void* p1, const void* p2)
224 struct entry* e2 = (struct entry*)p2; 224 struct entry* e2 = (struct entry*)p2;
225 int criteria; 225 int criteria;
226 226
227 if (e1->attr & ATTR_DIRECTORY && e2->attr & ATTR_DIRECTORY) 227 if (cmp_data.sort_dir == SORT_AS_FILE)
228 { /* treat as two files */
229 criteria = global_settings.sort_file;
230 }
231 else if (e1->attr & ATTR_DIRECTORY && e2->attr & ATTR_DIRECTORY)
228 { /* two directories */ 232 { /* two directories */
229 criteria = cmp_data.sort_dir; 233 criteria = cmp_data.sort_dir;
230 234
@@ -326,18 +330,17 @@ int ft_load(struct tree_context* c, const char* tempdir)
326 info = dir_get_info(dir, entry); 330 info = dir_get_info(dir, entry);
327 len = strlen((char *)entry->d_name); 331 len = strlen((char *)entry->d_name);
328 332
329 /* skip directories . and .. */
330 if ((info.attribute & ATTR_DIRECTORY) &&
331 (((len == 1) && (!strncmp((char *)entry->d_name, ".", 1))) ||
332 ((len == 2) && (!strncmp((char *)entry->d_name, "..", 2))))) {
333 continue;
334 }
335
336 /* Skip FAT volume ID */ 333 /* Skip FAT volume ID */
337 if (info.attribute & ATTR_VOLUME_ID) { 334 if (info.attribute & ATTR_VOLUME_ID) {
338 continue; 335 continue;
339 } 336 }
340 337
338 dptr->attr = info.attribute;
339 int dir_attr = (dptr->attr & ATTR_DIRECTORY);
340 /* skip directories . and .. */
341 if (dir_attr && is_dotdir_name(entry->d_name))
342 continue;
343
341 /* filter out dotfiles and hidden files */ 344 /* filter out dotfiles and hidden files */
342 if (*c->dirfilter != SHOW_ALL && 345 if (*c->dirfilter != SHOW_ALL &&
343 ((entry->d_name[0]=='.') || 346 ((entry->d_name[0]=='.') ||
@@ -345,48 +348,45 @@ int ft_load(struct tree_context* c, const char* tempdir)
345 continue; 348 continue;
346 } 349 }
347 350
348 dptr->attr = info.attribute;
349 int dir_attr = (dptr->attr & ATTR_DIRECTORY);
350
351 /* check for known file types */ 351 /* check for known file types */
352 if ( !(dir_attr) ) 352 if ( !(dir_attr) )
353 dptr->attr |= filetype_get_attr((char *)entry->d_name); 353 dptr->attr |= filetype_get_attr((char *)entry->d_name);
354 354
355 int file_attr = (dptr->attr & FILE_ATTR_MASK); 355 int file_attr = (dptr->attr & FILE_ATTR_MASK);
356 356
357#define CHK_FT(show,attr) (*c->dirfilter == (show) && file_attr != (attr))
357 /* filter out non-visible files */ 358 /* filter out non-visible files */
358 if ((!(dir_attr) && ((*c->dirfilter == SHOW_PLAYLIST && 359 if ((!(dir_attr) && (CHK_FT(SHOW_PLAYLIST, FILE_ATTR_M3U) ||
359 file_attr != FILE_ATTR_M3U) || 360 (CHK_FT(SHOW_MUSIC, FILE_ATTR_AUDIO) && file_attr != FILE_ATTR_M3U) ||
360 ((*c->dirfilter == SHOW_MUSIC && file_attr != FILE_ATTR_AUDIO) &&
361 file_attr != FILE_ATTR_M3U) ||
362 (*c->dirfilter == SHOW_SUPPORTED && !filetype_supported(dptr->attr)))) || 361 (*c->dirfilter == SHOW_SUPPORTED && !filetype_supported(dptr->attr)))) ||
363 (*c->dirfilter == SHOW_WPS && file_attr != FILE_ATTR_WPS) || 362 CHK_FT(SHOW_WPS, FILE_ATTR_WPS) ||
364 (*c->dirfilter == SHOW_FONT && file_attr != FILE_ATTR_FONT) || 363 CHK_FT(SHOW_FONT, FILE_ATTR_FONT) ||
365 (*c->dirfilter == SHOW_SBS && file_attr != FILE_ATTR_SBS) || 364 CHK_FT(SHOW_SBS, FILE_ATTR_SBS) ||
366#if CONFIG_TUNER 365#if CONFIG_TUNER
367 (*c->dirfilter == SHOW_FMS && file_attr != FILE_ATTR_FMS) || 366 CHK_FT(SHOW_FMS, FILE_ATTR_FMS) ||
367 CHK_FT(SHOW_FMR, FILE_ATTR_FMR) ||
368#endif 368#endif
369#ifdef HAVE_REMOTE_LCD 369#ifdef HAVE_REMOTE_LCD
370 (*c->dirfilter == SHOW_RWPS && file_attr != FILE_ATTR_RWPS) || 370 CHK_FT(SHOW_RWPS, FILE_ATTR_RWPS) ||
371 (*c->dirfilter == SHOW_RSBS && file_attr != FILE_ATTR_RSBS) || 371 CHK_FT(SHOW_RSBS, FILE_ATTR_RSBS) ||
372#if CONFIG_TUNER 372#if CONFIG_TUNER
373 (*c->dirfilter == SHOW_RFMS && file_attr != FILE_ATTR_RFMS) || 373 CHK_FT(SHOW_RFMS, FILE_ATTR_RFMS) ||
374#endif
375#endif 374#endif
376#if CONFIG_TUNER
377 (*c->dirfilter == SHOW_FMR && file_attr != FILE_ATTR_FMR) ||
378#endif 375#endif
379 (*c->dirfilter == SHOW_M3U && file_attr != FILE_ATTR_M3U) || 376 CHK_FT(SHOW_M3U, FILE_ATTR_M3U) ||
380 (*c->dirfilter == SHOW_CFG && file_attr != FILE_ATTR_CFG) || 377 CHK_FT(SHOW_CFG, FILE_ATTR_CFG) ||
381 (*c->dirfilter == SHOW_LNG && file_attr != FILE_ATTR_LNG) || 378 CHK_FT(SHOW_LNG, FILE_ATTR_LNG) ||
382 (*c->dirfilter == SHOW_MOD && file_attr != FILE_ATTR_MOD) || 379 CHK_FT(SHOW_MOD, FILE_ATTR_MOD) ||
383 (*c->dirfilter == SHOW_PLUGINS && file_attr != FILE_ATTR_ROCK && 380 /* show first level directories */
384 file_attr != FILE_ATTR_LUA && 381 ((!(dir_attr) || c->dirlevel > 0) &&
385 file_attr != FILE_ATTR_OPX) || 382 CHK_FT(SHOW_PLUGINS, FILE_ATTR_ROCK) &&
383 file_attr != FILE_ATTR_LUA &&
384 file_attr != FILE_ATTR_OPX) ||
386 (callback_show_item && !callback_show_item(entry->d_name, dptr->attr, c))) 385 (callback_show_item && !callback_show_item(entry->d_name, dptr->attr, c)))
387 { 386 {
388 continue; 387 continue;
389 } 388 }
389#undef CHK_FT
390 390
391 if (len > c->cache.name_buffer_size - name_buffer_used - 1) { 391 if (len > c->cache.name_buffer_size - name_buffer_used - 1) {
392 /* Tell the world that we ran out of buffer space */ 392 /* Tell the world that we ran out of buffer space */
@@ -408,7 +408,9 @@ int ft_load(struct tree_context* c, const char* tempdir)
408 c->dirlength = files_in_dir; 408 c->dirlength = files_in_dir;
409 closedir(dir); 409 closedir(dir);
410 410
411 cmp_data.sort_dir = c->sort_dir; 411 /* allow directories to be sorted into file list */
412 cmp_data.sort_dir = (*c->dirfilter == SHOW_PLUGINS) ? SORT_AS_FILE : c->sort_dir;
413
412 if (global_settings.sort_case) 414 if (global_settings.sort_case)
413 { 415 {
414 if (global_settings.interpret_numbers == SORT_INTERPRET_AS_NUMBER) 416 if (global_settings.interpret_numbers == SORT_INTERPRET_AS_NUMBER)
diff --git a/apps/plugins/CATEGORIES b/apps/plugins/CATEGORIES
index db0eb70fc4..c91d02ade8 100644
--- a/apps/plugins/CATEGORIES
+++ b/apps/plugins/CATEGORIES
@@ -57,7 +57,6 @@ lastfm_scrobbler_viewer,viewers
57logo,demos 57logo,demos
58lrcplayer,apps 58lrcplayer,apps
59lua,viewers 59lua,viewers
60lua_scripts,demos
61fractals,demos 60fractals,demos
62main_menu_config,apps 61main_menu_config,apps
63matrix,demos 62matrix,demos
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES
index ff08074f82..8028758ef0 100644
--- a/apps/plugins/SOURCES
+++ b/apps/plugins/SOURCES
@@ -117,7 +117,6 @@ metronome.c
117#if PLUGIN_BUFFER_SIZE >= 0x80000 117#if PLUGIN_BUFFER_SIZE >= 0x80000
118boomshine.lua 118boomshine.lua
119picross.lua 119picross.lua
120lua_scripts.lua
121#ifdef HAVE_LCD_COLOR 120#ifdef HAVE_LCD_COLOR
122pixel-painter.lua 121pixel-painter.lua
123#endif /* HAVE_LCD_COLOR */ 122#endif /* HAVE_LCD_COLOR */
diff --git a/apps/plugins/lua/include_lua/dbgettags.lua b/apps/plugins/lua/include_lua/dbgettags.lua
new file mode 100644
index 0000000000..8e9f26393d
--- /dev/null
+++ b/apps/plugins/lua/include_lua/dbgettags.lua
@@ -0,0 +1,119 @@
1-- dbgettags.lua Bilgus 2017
2--[[
3/***************************************************************************
4 * __________ __ ___.
5 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
6 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
7 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
8 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
9 * \/ \/ \/ \/ \/
10 * $Id$
11 *
12 * Copyright (C) 2017 William Wilgus
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23]]
24
25require("actions")
26local CANCEL_BUTTON = rb.actions.PLA_CANCEL
27
28local sINVALIDDATABASE = "Invalid Database"
29local sERROROPENING = "Error opening"
30
31-- tag cache header
32sTCVERSION = string.char(0x10)
33sTCHEADER = string.reverse("TCH" .. sTCVERSION)
34DATASZ = 4 -- int32_t
35TCHSIZE = 3 * DATASZ -- 3 x int32_t
36
37-- Converts array of bytes to proper endian
38function bytesLE_n(str)
39 str = str or ""
40 local tbyte={str:byte(1, -1)}
41 local bpos = 1
42 local num = 0
43 for k = 1,#tbyte do -- (k = #t, 1, -1 for BE)
44 num = num + tbyte[k] * bpos
45 bpos = bpos * 256
46 end
47 return num
48end
49
50-- uses database files to retrieve database tags
51-- adds all unique tags into a lua table
52-- ftable is optional
53function get_tags(filename, hstr, ftable)
54
55 if not filename then return end
56 if not ftable then ftable = {} end
57 hstr = hstr or filename
58
59 local file = io.open('/' .. filename or "", "r") --read
60 if not file then rb.splash(100, sERROROPENING .. " " .. filename) return end
61
62 local fsz = file:seek("end")
63
64 local posln = 0
65 local tag_len = TCHSIZE
66 local idx
67
68 local function readchrs(count)
69 if posln >= fsz then return nil end
70 file:seek("set", posln)
71 posln = posln + count
72 return file:read(count)
73 end
74
75 -- check the header and get size + #entries
76 local tagcache_header = readchrs(DATASZ) or ""
77 local tagcache_sz = readchrs(DATASZ) or ""
78 local tagcache_entries = readchrs(DATASZ) or ""
79
80 if tagcache_header ~= sTCHEADER or
81 bytesLE_n(tagcache_sz) ~= (fsz - TCHSIZE) then
82 rb.splash(100, sINVALIDDATABASE .. " " .. filename)
83 return
84 end
85
86 -- local tag_entries = bytesLE_n(tagcache_entries)
87
88 for k, v in pairs(ftable) do ftable[k] = nil end -- clear table
89 ftable[1] = hstr
90
91 local tline = #ftable + 1
92 ftable[tline] = ""
93
94 local str = ""
95
96 while true do
97 tag_len = bytesLE_n(readchrs(DATASZ))
98 readchrs(DATASZ) -- idx = bytesLE_n(readchrs(DATASZ))
99 str = readchrs(tag_len) or ""
100 str = string.match(str, "(%Z+)%z") -- \0 terminated string
101
102 if str then
103 if ftable[tline - 1] ~= str then -- Remove dupes
104 ftable[tline] = str
105 tline = tline + 1
106 end
107 elseif posln >= fsz then
108 break
109 end
110
111 if rb.get_plugin_action(0) == CANCEL_BUTTON then
112 break
113 end
114 end
115
116 file:close()
117
118 return ftable
119end -- get_tags
diff --git a/apps/plugins/lua/include_lua/filebrowse.lua b/apps/plugins/lua/include_lua/filebrowse.lua
new file mode 100755
index 0000000000..0640ec3764
--- /dev/null
+++ b/apps/plugins/lua/include_lua/filebrowse.lua
@@ -0,0 +1,241 @@
1--[[
2/***************************************************************************
3 * __________ __ ___.
4 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
5 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
6 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
7 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
8 * \/ \/ \/ \/ \/
9 * $Id$
10 *
11 * Copyright (C) 2017 William Wilgus
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22]]
23if ... == nil then rb.splash(rb.HZ * 3, "use 'require'") end
24require("printtable")
25local _lcd = require("lcd")
26local _timer = require("timer")
27
28--------------------------------------------------------------------------------
29--[[ returns a sorted tables of directories and (another) of files
30-- path is the starting path; norecurse == true.. only that path will be searched
31-- findfile & finddir are definable search functions
32-- if not defined all files/dirs are returned if false is passed.. none
33-- or you can provide your own function see below..
34-- f_t and d_t allow you to pass your own tables for re-use but isn't necessary
35]]
36local function get_files(path, norecurse, finddir, findfile, sort_by, f_t, d_t)
37 local quit = false
38 local sort_by_function -- forward declaration
39 local filepath_function -- forward declaration
40 local files = f_t or {}
41 local dirs = d_t or {}
42
43 local function f_filedir(name)
44 --default find function
45 -- example: return name:find(".mp3", 1, true) ~= nil
46 if name:len() <= 2 and (name == "." or name == "..") then
47 return false
48 end
49 return true
50 end
51 local function d_filedir(name)
52 --default discard function
53 return false
54 end
55
56 if finddir == nil then
57 finddir = f_filedir
58 elseif type(finddir) ~= "function" then
59 finddir = d_filedir
60 end
61
62 if findfile == nil then
63 findfile = f_filedir
64 elseif type(findfile) ~= "function" then
65 findfile = d_filedir
66 end
67
68 local function _get_files(path, cancelbtn)
69 local sep = ""
70 local filepath
71 local finfo_t
72 if string.sub(path, - 1) ~= "/" then sep = "/" end
73 for fname, isdir, finfo_t in luadir.dir(path, true) do
74 if isdir and finddir(fname) then
75 table.insert(dirs, path .. sep ..fname)
76 elseif not isdir and findfile(fname) then
77 filepath = filepath_function(path, sep, fname, finfo_t.attribute, finfo_t.size, finfo_t.time)
78 table.insert(files, filepath)
79 end
80
81 if rb.get_plugin_action(0) == cancelbtn then
82 return true
83 end
84 end
85 end
86
87
88
89 local function cmp_alphanum (op1, op2)
90 local type1= type(op1)
91 local type2 = type(op2)
92
93 if type1 ~= type2 then
94 return type1 < type2
95 else
96 if type1 == "string" then
97 op1 = op1:upper()
98 op2 = op2:upper()
99 return sort_by_function(op1, op2)
100 end
101 return op1 < op2
102 end
103 end
104
105 _lcd:splashf(1, "Searching for Files")
106
107 if sort_by == "name" then
108 sort_by_function = function(s1, s2) return s1 < s2 end
109 filepath_function = function(path, sep, fname, fattrib, fsize, ftime)
110 return string.format("%s%s%s;", path, sep, fname)
111 end
112 elseif sort_by == "size" then
113 filepath_function = function(path, sep, fname, fattrib, fsize, ftime)
114 return string.format("%s%s%s; At:%d, Sz:%d, Tm:%d", path, sep, fname, fattrib, fsize, ftime)
115 end
116 sort_by_function = function(s1, s2)
117 local v1, v2
118 v1 = string.match(s1, "SZ:(%d+)")
119 v2 = string.match(s2, "SZ:(%d+)")
120 if v1 or v2 then
121 return tonumber(v1 or 0) < tonumber(v2 or 0)
122 end
123 return s1 < s2
124 end
125 elseif sort_by == "date" then
126 filepath_function = function(path, sep, fname, fattrib, fsize, ftime)
127 return string.format("%s%s%s; At:%d, Sz:%d, Tm:%d", path, sep, fname, fattrib, fsize, ftime)
128 end
129 sort_by_function = function(s1, s2)
130 local v1, v2
131 v1 = string.match(s1, "TM:(%d+)")
132 v2 = string.match(s2, "TM:(%d+)")
133 if v1 or v2 then
134 return tonumber(v1 or 0) < tonumber(v2 or 0)
135 end
136 return s1 < s2
137 end
138 end
139
140 table.insert(dirs, path) -- root
141
142 for key,value in pairs(dirs) do
143 --luadir.dir may error out so we need to do the call protected
144 -- _get_files(value, CANCEL_BUTTON)
145 _, quit = pcall(_get_files, value, CANCEL_BUTTON)
146
147 if quit == true or norecurse then
148 break;
149 end
150 end
151
152 table.sort(files, cmp_alphanum)
153 table.sort(dirs, cmp_alphanum)
154
155 return dirs, files
156end -- get_files
157--------------------------------------------------------------------------------
158
159-- uses print_table and get_files to display simple file browser
160-- sort_by "date" "name" "size"
161-- descending true/false
162function file_choose(dir, title, sort_by, descending)
163 local dstr, hstr = ""
164 if not title then
165 dstr = "%d items found in %0d.%02d seconds"
166 else
167 hstr = title
168 end
169
170 if not sort_by then sort_by = "name" end
171 sort_by = sort_by:lower()
172
173 -- returns whole seconds and remainder
174 local function tick2seconds(ticks)
175 local secs = (ticks / rb.HZ)
176 local csecs = (ticks - (secs * rb.HZ))
177 return secs, csecs
178 end
179
180 local norecurse = true
181 local f_finddir = nil -- function to match directories; nil all, false none
182 local f_findfile = nil -- function to match files; nil all, false none
183
184 local p_settings = {wrap = true, hasheader = true}
185
186 local timer
187 local files = {}
188 local dirs = {}
189 local item = 1
190 _lcd:clear()
191
192 while item > 0 do
193 if not title then
194 timer = _timer()
195 end
196
197 dirs, files = get_files(dir, norecurse, f_finddir, f_findfile, sort_by, dirs, files)
198
199 local parentdir = dirs[1]
200 for i = 1, #dirs do
201 dirs[i] = "\t" .. dirs[i]
202 end
203
204 if not descending then
205 for i = 1, #files do
206 -- only store file name .. strip attributes from end
207 table.insert(dirs, "\t" .. string.match(files[i], "[^;]+") or "?")
208 end
209 else
210 for i = #files, 1, -1 do
211 -- only store file name .. strip attributes from end
212 table.insert(dirs, "\t" .. string.match(files[i], "[^;]+") or "?")
213 end
214 end
215 for i=1, #files do files[i] = nil end -- empty table for reuse
216
217 if not title then
218 hstr = string.format(dstr, #dirs - 1, tick2seconds(timer:stop()))
219 end
220
221 table.insert(dirs, 1, hstr)
222
223 item = print_table(dirs, #dirs, p_settings)
224
225 -- If item was selected follow directory or return filename
226 if item > 0 then
227 dir = string.gsub(dirs[item], "%c+","")
228 if not rb.dir_exists("/" .. dir) then
229 return dir
230 end
231 end
232
233 if dir == parentdir then
234 dir = dir:sub(1, dir:match(".*()/") - 1)
235 if dir == "" then dir = "/" end
236 end
237 for i=1, #dirs do dirs[i] = nil end -- empty table for reuse
238
239 end
240end -- file_choose
241--------------------------------------------------------------------------------
diff --git a/apps/plugins/lua/include_lua/fileviewers.lua b/apps/plugins/lua/include_lua/fileviewers.lua
new file mode 100755
index 0000000000..c686f3eeda
--- /dev/null
+++ b/apps/plugins/lua/include_lua/fileviewers.lua
@@ -0,0 +1,468 @@
1--[[
2/***************************************************************************
3 * __________ __ ___.
4 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
5 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
6 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
7 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
8 * \/ \/ \/ \/ \/
9 * $Id$
10 *
11 * Copyright (C) 2017 William Wilgus
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22]]
23if ... == nil then rb.splash(rb.HZ * 3, "use 'require'") end
24require("printtable")
25local _clr = require("color")
26local _lcd = require("lcd")
27local _print = require("print")
28local _timer = require("timer")
29
30require("actions")
31local CANCEL_BUTTON = rb.actions.PLA_CANCEL
32--------------------------------------------------------------------------------
33-- builds an index of byte position of every line at each bufsz increment
34-- in filename; bufsz == 1 would be every line; saves to filename.ext.idx_ext
35-- lnbyte should be nil for text files and number of bytes per line for binary
36local function build_file_index(filename, idx_ext, bufsz, lnbyte)
37
38 if not filename then return end
39 local file = io.open('/' .. filename, "r") --read
40 if not file then _lcd:splashf(100, "Can't open %s", filename) return end
41 local fsz = file:seek("end")
42 local fsz_kb = fsz / 1024
43 local count
44 local ltable = {0} --first index is the beginning of the file
45 local timer = _timer()
46 local fread
47 _lcd:splashf(100, "Indexing file %d Kb", (fsz / 1024))
48
49 if lnbyte then
50 fread = function(f) return f:read(lnbyte) end
51 else
52 lnbyte = -1
53 fread = function(f) return f:read("*l") end
54 end
55
56 file:seek("set", 0)
57 for i = 1, fsz do
58 if i % bufsz == 0 then
59 local loc = file:seek()
60 ltable[#ltable + 1] = loc
61 _lcd:splashf(1, "Parsing %d of %d Kb", loc / 1024, fsz_kb)
62 end
63 if rb.get_plugin_action(0) == CANCEL_BUTTON then
64 return
65 end
66 if not fread(file) then
67 count = i
68 break
69 end
70 end
71
72 local fileidx = io.open('/' .. filename .. idx_ext, "w+") -- write/erase
73 if fileidx then
74 fileidx:write(fsz .. "\n")
75 fileidx:write(count .. "\n")
76 fileidx:write(bufsz .. "\n")
77 fileidx:write(lnbyte .. "\n")
78 fileidx:write(table.concat(ltable, "\n"))
79 fileidx:close()
80 _lcd:splashf(100, "Finished in %d seconds", timer.stop() / rb.HZ)
81 collectgarbage("collect")
82 else
83 error("unable to save index file")
84 end
85end -- build_file_index
86--------------------------------------------------------------------------------
87
88--- returns size of original file, total lines buffersize, and table filled
89-- with line offsets in index file -> filename
90local function load_index_file(filename)
91 local filesz, count, bufsz, lnbyte
92 local ltable
93 local fileidx = io.open('/' .. filename, "r") --read
94 if fileidx then
95 local idx = -3
96 ltable = {}
97 fileidx:seek("set", 0)
98 for line in fileidx:lines() do
99 if idx == -3 then
100 filesz = tonumber(line)
101 elseif idx == -2 then
102 count = tonumber(line)
103 elseif idx == -1 then
104 bufsz = tonumber(line)
105 elseif idx == 0 then
106 lnbyte = tonumber(line)
107 else
108 ltable[idx] = tonumber(line)
109 end
110 idx = idx + 1
111 end
112 fileidx:close()
113 end
114 return lnbyte, filesz, count, bufsz, ltable
115end -- load_index_file
116--------------------------------------------------------------------------------
117
118-- creates a fixed index with fixed line lengths, perfect for viewing hex files
119-- not so great for reading text files but works as a fallback
120local function load_fixed_index(bytesperline, filesz, bufsz)
121 local lnbyte = bytesperline
122 local count = (filesz + lnbyte - 1) / lnbyte + 1
123 local idx_t = {} -- build index
124 for i = 0, filesz, bufsz do
125 idx_t[#idx_t + 1] = lnbyte * i
126 end
127 return lnbyte, filesz, count, bufsz, idx_t
128end -- load_fixed_index
129--------------------------------------------------------------------------------
130
131-- uses print_table to display a whole file
132function print_file(filename, maxlinelen, settings)
133
134 if not filename then return end
135 local file = io.open('/' .. filename or "", "r") --read
136 if not file then _lcd:splashf(100, "Can't open %s", filename) return end
137 maxlinelen = 33
138 local hstr = filename
139 local ftable = {}
140 table.insert(ftable, 1, hstr)
141
142 local tline = #ftable + 1
143 local remln = maxlinelen
144 local posln = 1
145
146 for line in file:lines() do
147 if line then
148 if maxlinelen then
149 if line == "" then
150 ftable[tline] = ftable[tline] or ""
151 tline = tline + 1
152 remln = maxlinelen
153 else
154 line = line:match("%w.+") or ""
155 end
156 local linelen = line:len()
157 while linelen > 0 do
158
159 local fsp = line:find("%s", posln + remln - 5) or 0x0
160 fsp = fsp - (posln + remln)
161 if fsp >= 0 then
162 local fspr = fsp
163 fsp = line:find("%s", posln + remln) or linelen
164 fsp = fsp - (posln + remln)
165 if math.abs(fspr) < fsp then fsp = fspr end
166 end
167 if fsp > 5 or fsp < -5 then fsp = 0 end
168
169 local str = line:sub(posln, posln + remln + fsp)
170 local slen = str:len()
171 ftable[tline] = ftable[tline] or ""
172 ftable[tline] = ftable[tline] .. str
173 linelen = linelen - slen
174 if linelen > 0 then
175 tline = tline + 1
176 posln = posln + slen
177 remln = maxlinelen
178 --loop continues
179 else
180 ftable[tline] = ftable[tline] .. " "
181 remln = maxlinelen - slen
182 posln = 1
183 --loop ends
184 end
185
186 end
187 else
188 ftable[#ftable + 1] = line
189 end
190
191
192 end
193 end
194
195 file:close()
196
197 _lcd:clear()
198 _print.clear()
199
200 if not settings then
201 settings = {}
202 settings.justify = "center"
203 settings.wrap = true
204 settings.msel = true
205 end
206 settings.hasheader = true
207 settings.co_routine = nil
208 settings.ovfl = "manual"
209
210 local sel =
211 print_table(ftable, #ftable, settings)
212
213 _lcd:splashf(rb.HZ * 2, "%d items {%s}", #sel, table.concat(sel, ", "))
214 ftable = nil
215end -- print_file
216--------------------------------------------------------------------------------
217
218-- uses print_table to display a portion of a file
219function print_file_increment(filename, settings)
220
221 if not filename then return end
222 local file = io.open('/' .. filename, "r") --read
223 if not file then _lcd:splashf(100, "Can't open %s", filename) return end
224 local fsz = file:seek("end")
225 local bsz = 1023
226 --if small file do it the easier way and load whole file to table
227 if fsz < 60 * 1024 then
228 file:close()
229 print_file(filename, settings)
230 return
231 end
232
233 local ext = ".idx"
234 local lnbyte, filesz, count, bufsz, idx_t = load_index_file(filename .. ext)
235
236 if not idx_t or fsz ~= filesz then -- build file index
237 build_file_index(filename, ext, bsz)
238 lnbyte, filesz, count, bufsz, idx_t = load_index_file(filename .. ext)
239 end
240
241 -- if invalid or user canceled creation fallback to a fixed index
242 if not idx_t or fsz ~= filesz or count <= 0 then
243 _lcd:splashf(rb.HZ * 5, "Unable to read file index %s", filename .. ext)
244 lnbyte, filesz, count, bufsz, idx_t = load_fixed_index(32, fsz, bsz)
245 end
246
247 if not idx_t or fsz ~= filesz or count <= 0 then
248 _lcd:splashf(rb.HZ * 5, "Unable to load file %s", filename)
249 return
250 end
251
252 local hstr = filename
253 local file_t = setmetatable({},{__mode = "kv"}) --weak keys and values
254 -- this allows them to be garbage collected as space is needed
255 -- rebuilds when needed
256 local ovf = 0
257 local lpos = 1
258 local timer = _timer()
259 file:seek("set", 0)
260
261 function print_co()
262 while true do
263 collectgarbage("step")
264 file_t[1] = hstr --position 1 is ALWAYS header/title
265
266 for i = 1, bufsz + ovf do
267 file_t[lpos + i] = file:read ("*l")
268 end
269 ovf = 0
270 lpos = lpos + bufsz
271
272 local bpos = coroutine.yield()
273
274 if bpos <= lpos then -- roll over or scroll up
275 bpos = (bpos - bufsz) + bpos % bufsz
276 timer:check(true)
277 end
278
279 lpos = bpos - bpos % bufsz
280
281 if lpos < 1 then
282 lpos = 1
283 elseif lpos > count - bufsz then -- partial fill
284 ovf = count - bufsz - lpos
285 end
286 --get position in file of the nearest indexed line
287 file:seek("set", idx_t[bpos / bufsz + 1])
288
289 -- on really large files if it has been more than 10 minutes
290 -- since the user scrolled up the screen wipe out the prior
291 -- items to free memory
292 if lpos % 5000 == 0 and timer:check() > rb.HZ * 600 then
293 for i = 1, lpos - 100 do
294 file_t[i] = nil
295 end
296 end
297
298 end
299 end
300
301 co = coroutine.create(print_co)
302 _lcd:clear()
303 _print.clear()
304
305 if not settings then
306 settings = {}
307 settings.justify = "center"
308 settings.wrap = true
309 end
310 settings.hasheader = true
311 settings.co_routine = co
312 settings.msel = false
313 settings.ovfl = "manual"
314
315 table.insert(file_t, 1, hstr) --position 1 is header/title
316 local sel =
317 print_table(file_t, count, settings)
318 file:close()
319 idx_t = nil
320 file_t = nil
321 return sel
322end --print_file_increment
323--------------------------------------------------------------------------------
324function print_file_hex(filename, bytesperline, settings)
325
326 if not filename then return end
327 local file = io.open('/' .. filename, "r") --read
328 if not file then _lcd:splashf(100, "Can't open %s", filename) return end
329 local hstr = filename
330 local bpl = bytesperline
331 local fsz = file:seek("end")
332--[[
333 local filesz = file:seek("end")
334 local bufsz = 1023
335 local lnbyte = bytesperline
336 local count = (filesz + lnbyte - 1) / lnbyte + 1
337
338 local idx_t = {} -- build index
339 for i = 0, filesz, bufsz do
340 idx_t[#idx_t + 1] = lnbyte * i
341 end]]
342
343 local lnbyte, filesz, count, bufsz, idx_t = load_fixed_index(bpl, fsz, 1023)
344
345 local file_t = setmetatable({},{__mode = "kv"}) --weak keys and values
346 -- this allows them to be garbage collected as space is needed
347 -- rebuilds when needed
348 local ovf = 0
349 local lpos = 1
350 local timer = _timer()
351 file:seek("set", 0)
352
353 function hex_co()
354 while true do
355 collectgarbage("step")
356 file_t[1] = hstr --position 1 is ALWAYS header/title
357
358 for i = 1, bufsz + ovf do
359 local pos = file:seek()
360 local s = file:read (lnbyte)
361 if not s then -- EOF
362 file_t[lpos + i] = ""
363 break;
364 end
365 local s_len = s:len()
366
367 if s_len > 0 then
368 local fmt = "0x%04X: " .. string.rep("%02X ", s_len)
369 local schrs = " " .. s:gsub("(%c)", " . ")
370 file_t[lpos + i] = string.format(fmt, pos, s:byte(1, s_len)) ..
371 schrs
372 else
373 file_t[lpos + i] = string.format("0x%04X: ", pos)
374 end
375 end
376 ovf = 0
377 lpos = lpos + bufsz
378
379 local bpos = coroutine.yield()
380
381 if bpos < lpos then -- roll over or scroll up
382 bpos = (bpos - bufsz) + bpos % bufsz
383 timer:check(true)
384 end
385
386 lpos = bpos - bpos % bufsz
387
388 if lpos < 1 then
389 lpos = 1
390 elseif lpos > count - bufsz then -- partial fill
391 ovf = count - bufsz - lpos
392 end
393 --get position in file of the nearest indexed line
394 file:seek("set", idx_t[bpos / bufsz + 1])
395
396 -- on really large files if it has been more than 10 minutes
397 -- since the user scrolled up the screen wipe out the prior
398 -- items to free memory
399 if lpos % 10000 == 0 and timer:check() > rb.HZ * 600 then
400 for i = 1, lpos - 100 do
401 file_t[i] = nil
402 end
403 end
404
405 end
406 end
407
408 co = coroutine.create(hex_co)
409
410 local function repl(char)
411 local ret = ""
412 if char:sub(1,2) == "0x" then
413 return string.format("%dd:", tonumber(char:sub(3, -2), 16))
414 else
415 return string.format("%03d ", tonumber(char, 16))
416 end
417 end
418
419
420 _lcd:clear()
421 _print.clear()
422
423 local sel, start, vcur = 1
424 table.insert(file_t, 1, hstr) --position 1 is header/title
425
426 if not settings then
427 settings = {}
428 settings.justify = "left"
429 settings.wrap = true
430 settings.msel = false
431 settings.hfgc = _clr.set( 0, 000, 000, 000)
432 settings.hbgc = _clr.set(-1, 255, 255, 255)
433 settings.ifgc = _clr.set(-1, 255, 255, 255)
434 settings.ibgc = _clr.set( 0, 000, 000, 000)
435 settings.iselc = _clr.set( 1, 000, 200, 100)
436 end
437
438 settings.hasheader = true
439 settings.co_routine = co
440 settings.start = start
441 settings.curpos = vcur
442 settings.ovfl = "manual"
443
444 while sel > 0 do
445 settings.start = start
446 settings.curpos = vcur
447
448 sel, start, vcur = print_table(file_t, count, settings)
449
450 if sel > 1 and file_t[sel] then -- flips between hex and decimal
451 local s = file_t[sel]
452 if s:sub(-1) == "\b" then
453 file_t[sel] = nil
454 ovf = -(bufsz - 1)
455 coroutine.resume(co, sel) --rebuild this item
456 else
457 s = s:gsub("(0x%x+:)", repl) .. "\b"
458 file_t[sel] = s:gsub("(%x%x%s)", repl) .. "\b"
459 end
460 end
461 end
462
463 file:close()
464 idx_t = nil
465 file_t = nil
466 return sel
467end -- print_file_hex
468--------------------------------------------------------------------------------
diff --git a/apps/plugins/lua/lua.make b/apps/plugins/lua/lua.make
index 60dfd24cdd..c85182880b 100644
--- a/apps/plugins/lua/lua.make
+++ b/apps/plugins/lua/lua.make
@@ -16,14 +16,7 @@ LUA_OBJ := $(call c2obj, $(LUA_SRC))
16OTHER_SRC += $(LUA_SRC) 16OTHER_SRC += $(LUA_SRC)
17 17
18LUA_INCLUDEDIR := $(LUA_SRCDIR)/include_lua 18LUA_INCLUDEDIR := $(LUA_SRCDIR)/include_lua
19LUA_INCLUDELIST := $(addprefix $(LUA_BUILDDIR)/,audio.lua blit.lua color.lua \ 19LUA_INCLUDELIST := $(wildcard $(LUA_INCLUDEDIR)/*.lua)
20 draw.lua draw_floodfill.lua draw_poly.lua draw_num.lua \
21 draw_text.lua files.lua image.lua image_save.lua lcd.lua \
22 math_ex.lua print.lua timer.lua playlist.lua pcm.lua \
23 sound.lua rbcompat.lua rbsettings.lua poly_points.lua \
24 printtable.lua printmenus.lua printsubmenu.lua \
25 menubuttons.lua menucoresettings.lua create_kbd_layout.lua \
26 temploader.lua)
27 20
28ifndef APP_TYPE 21ifndef APP_TYPE
29 ROCKS += $(LUA_BUILDDIR)/lua.rock 22 ROCKS += $(LUA_BUILDDIR)/lua.rock
@@ -31,6 +24,7 @@ else
31 ### simulator 24 ### simulator
32 ROCKS += $(LUA_BUILDDIR)/lua.rock 25 ROCKS += $(LUA_BUILDDIR)/lua.rock
33endif 26endif
27all: $(subst $(LUA_INCLUDEDIR)/,$(LUA_BUILDDIR)/,$(LUA_INCLUDELIST))
34 28
35$(LUA_BUILDDIR)/lua.rock: $(LUA_OBJ) $(TLSFLIB) $(LUA_BUILDDIR)/actions.lua $(LUA_BUILDDIR)/buttons.lua $(LUA_BUILDDIR)/settings.lua \ 29$(LUA_BUILDDIR)/lua.rock: $(LUA_OBJ) $(TLSFLIB) $(LUA_BUILDDIR)/actions.lua $(LUA_BUILDDIR)/buttons.lua $(LUA_BUILDDIR)/settings.lua \
36 $(LUA_BUILDDIR)/rocklib_aux.o $(LUA_BUILDDIR)/rb_defines.lua $(LUA_BUILDDIR)/sound_defines.lua \ 30 $(LUA_BUILDDIR)/rocklib_aux.o $(LUA_BUILDDIR)/rb_defines.lua $(LUA_BUILDDIR)/sound_defines.lua \
@@ -66,7 +60,7 @@ $(LUA_BUILDDIR)/rocklib_aux.o: $(LUA_BUILDDIR)/rocklib_aux.c
66 $(call PRINTS,CC $(<F))$(CC) $(INCLUDES) $(PLUGINFLAGS) -I $(LUA_SRCDIR) -c $< -o $@ 60 $(call PRINTS,CC $(<F))$(CC) $(INCLUDES) $(PLUGINFLAGS) -I $(LUA_SRCDIR) -c $< -o $@
67 61
68$(LUA_BUILDDIR)/%.lua: $(LUA_INCLUDEDIR)/%.lua | $(LUA_BUILDDIR) 62$(LUA_BUILDDIR)/%.lua: $(LUA_INCLUDEDIR)/%.lua | $(LUA_BUILDDIR)
69 $(call PRINTS,CP $(subst $(LUA_INCLUDEDIR)/,,$<))cp $< $@ 63 $(call PRINTS,CP $(notdir $<))cp $< $@
70 64
71$(LUA_BUILDDIR)/lua.refmap: $(LUA_OBJ) $(TLSFLIB) 65$(LUA_BUILDDIR)/lua.refmap: $(LUA_OBJ) $(TLSFLIB)
72 66
diff --git a/apps/plugins/lua_scripts/lua_scripts.lua b/apps/plugins/lua_scripts/lua_scripts.lua
new file mode 100644
index 0000000000..331611d389
--- /dev/null
+++ b/apps/plugins/lua_scripts/lua_scripts.lua
@@ -0,0 +1,172 @@
1--[[
2/***************************************************************************
3 * __________ __ ___.
4 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
5 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
6 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
7 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
8 * \/ \/ \/ \/ \/
9 * $Id$
10 *
11 * Copyright (C) 2017 William Wilgus
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22]]
23
24local scrpath = rb.current_path()
25
26package.path = scrpath .. "/?.lua;" .. package.path --add lua_scripts directory to path
27require("printmenus")
28
29rb.actions = nil
30package.loaded["actions"] = nil
31
32--------------------------------------------------------------------------------
33local Icon_Plugin = 0x9
34
35
36local function get_files(path, norecurse, finddir, findfile, f_t, d_t)
37
38 local quit = false
39
40 local files = f_t or {}
41 local dirs = d_t or {}
42
43 local function f_filedir(name)
44 --default find function
45 -- example: return name:find(".mp3", 1, true) ~= nil
46 if name:len() <= 2 and (name == "." or name == "..") then
47 return false
48 end
49 if string.sub(name, 1, 1) == '.' then
50 return false
51 end
52 if string.sub(name, -4) == ".lua" then
53 return true
54 end
55 return false
56 end
57 local function d_filedir(name)
58 --default discard function
59 return false
60 end
61
62 if finddir == nil then
63 finddir = f_filedir
64 elseif type(finddir) ~= "function" then
65 finddir = d_filedir
66 end
67
68 if findfile == nil then
69 findfile = f_filedir
70 elseif type(findfile) ~= "function" then
71 findfile = d_filedir
72 end
73
74 local function _get_files(path, cancelbtn)
75 local sep = ""
76 if string.sub(path, - 1) ~= "/" then sep = "/" end
77 for fname, isdir in luadir.dir(path) do
78
79 if isdir and finddir(fname) then
80 table.insert(dirs, path .. sep ..fname)
81 elseif not isdir and findfile(fname) then
82 table.insert(files, path .. sep ..fname)
83 end
84
85 if rb.get_plugin_action(0) == cancelbtn then
86 return true
87 end
88 end
89 end
90
91 local function cmp_alphanum (op1, op2)
92 local type1= type(op1)
93 local type2 = type(op2)
94
95 if type1 ~= type2 then
96 return type1 < type2
97 else
98 if type1 == "string" then
99 op1 = op1:upper()
100 op2 = op2:upper()
101 end
102 return op1 < op2
103 end
104 end
105
106 table.insert(dirs, path) -- root
107
108 for key,value in pairs(dirs) do
109 --luadir.dir may error out so we need to do the call protected
110 _, quit = pcall(_get_files, value, CANCEL_BUTTON)
111
112 if quit == true or norecurse then
113 break;
114 end
115 end
116
117 table.sort(files, cmp_alphanum)
118 table.sort(dirs, cmp_alphanum)
119
120 return dirs, files
121end -- get_files
122--------------------------------------------------------------------------------
123
124function icon_fn(item, icon)
125 if item ~= 0 then
126 icon = Icon_Plugin
127 else
128 icon = -1
129 end
130 return icon
131end
132
133-- uses print_table and get_files to display simple file browser
134function script_choose(dir, title)
135 local dstr
136 local hstr = title
137
138 local norecurse = true
139 local f_finddir = false -- function to match directories; nil all, false none
140 local f_findfile = nil -- function to match files; nil all, false none
141 local t_linedesc = {show_icons = true, icon_fn = icon_fn}
142 local p_settings = {wrap = true, hasheader = true, justify = "left", linedesc = t_linedesc}
143 local files = {}
144 local dirs = {}
145 local item = 1
146 rb.lcd_clear_display()
147
148 while item > 0 do
149 dirs, files = get_files(dir, norecurse, f_finddir, f_findfile, dirs, files)
150 for i=1, #dirs do dirs[i] = nil end -- empty table for reuse
151 table.insert(dirs, 1, hstr)
152 for i = 1, #files do
153 table.insert(dirs, "\t" .. string.gsub(files[i], ".*/",""))
154 end
155 --print_menu(menu_t, func_t, selected, settings, copy_screen)
156 _, item = print_menu(dirs, nil, 0, p_settings)
157
158 -- If item was selected follow directory or return filename
159 item = item or -1
160 if item > 0 then
161 dir = files[item - 1]
162 if not rb.dir_exists("/" .. dir) then
163 return dir
164 end
165 end
166
167 end
168end -- file_choose
169--------------------------------------------------------------------------------
170
171local script_path = script_choose(scrpath, "lua scripts")
172if script_path then rb.restart_lua(script_path) end
diff --git a/apps/plugins/lua_scripts/lua_scripts.make b/apps/plugins/lua_scripts/lua_scripts.make
index 2f46f9d74a..9151ab6d1c 100644
--- a/apps/plugins/lua_scripts/lua_scripts.make
+++ b/apps/plugins/lua_scripts/lua_scripts.make
@@ -10,7 +10,6 @@
10LUASCR_SRCDIR := $(APPSDIR)/plugins/lua_scripts 10LUASCR_SRCDIR := $(APPSDIR)/plugins/lua_scripts
11LUASCR_BUILDDIR := $(BUILDDIR)/apps/plugins/lua_scripts 11LUASCR_BUILDDIR := $(BUILDDIR)/apps/plugins/lua_scripts
12LUASCRS := $(wildcard $(LUASCR_SRCDIR)/*.lua) 12LUASCRS := $(wildcard $(LUASCR_SRCDIR)/*.lua)
13
14#DUMMY := $(info [${LUASCRS}]) 13#DUMMY := $(info [${LUASCRS}])
15 14
16DUMMY : all 15DUMMY : all
@@ -18,7 +17,6 @@ DUMMY : all
18all: $(subst $(LUASCR_SRCDIR)/,$(LUASCR_BUILDDIR)/,$(LUASCRS)) 17all: $(subst $(LUASCR_SRCDIR)/,$(LUASCR_BUILDDIR)/,$(LUASCRS))
19 18
20$(LUASCR_BUILDDIR)/%.lua: $(LUASCR_SRCDIR)/%.lua | $(LUASCR_BUILDDIR) 19$(LUASCR_BUILDDIR)/%.lua: $(LUASCR_SRCDIR)/%.lua | $(LUASCR_BUILDDIR)
21 $(call PRINTS,CP $(subst $(LUASCR_SRCDIR)/,,$<))cp $< $@ 20 $(call PRINTS,CP $(subst $(APPSDIR)/,,$<))cp $< $@
22
23$(LUASCR_BUILDDIR): 21$(LUASCR_BUILDDIR):
24 $(call PRINTS,MKDIR $@)mkdir -p $(LUASCR_BUILDDIR)/ 22 $(call PRINTS,MKDIR $@)mkdir -p $(LUASCR_BUILDDIR)/
diff --git a/apps/plugins/picross.lua b/apps/plugins/picross.lua
index 26ad57ee74..ec9b6ef7a9 100644
--- a/apps/plugins/picross.lua
+++ b/apps/plugins/picross.lua
@@ -24,7 +24,7 @@ local _clr = require("color") -- clrset, clrinc provides device independent co
24local _lcd = require("lcd") -- lcd helper functions 24local _lcd = require("lcd") -- lcd helper functions
25 25
26local plugindir = rb.PLUGIN_GAMES_DATA_DIR 26local plugindir = rb.PLUGIN_GAMES_DATA_DIR
27local userdir = plugindir .. "/picross" 27local userdir = plugindir .. "/.picross"
28 28
29local wrap = rb.settings.read('global_settings', rb.system.global_settings.list_wraparound) 29local wrap = rb.settings.read('global_settings', rb.system.global_settings.list_wraparound)
30wrap = (wrap or 1) == 1 30wrap = (wrap or 1) == 1
@@ -371,7 +371,7 @@ function State:loadSave()
371end 371end
372 372
373function State:loadDefault() 373function State:loadDefault()
374 self:loadFile(userdir .. '/picross_default.picross') 374 return self:loadFile(userdir .. '/picross_default.picross')
375end 375end
376 376
377function State:loadFile(path) 377function State:loadFile(path)
@@ -763,7 +763,9 @@ function viewPicture()
763end 763end
764 764
765if not State:loadSave() then 765if not State:loadSave() then
766 State:loadDefault() 766 if not State:loadDefault() then
767 return;
768 end
767end 769end
768 770
769local act = rb.actions 771local act = rb.actions
diff --git a/apps/plugins/picross/picross.make b/apps/plugins/picross/picross.make
index d34b251dac..ead5ba482a 100644
--- a/apps/plugins/picross/picross.make
+++ b/apps/plugins/picross/picross.make
@@ -8,7 +8,7 @@
8# 8#
9 9
10PICRSCR_SRCDIR := $(APPSDIR)/plugins/picross 10PICRSCR_SRCDIR := $(APPSDIR)/plugins/picross
11PICRSCR_BUILDDIR := $(BUILDDIR)/apps/plugins/picross 11PICRSCR_BUILDDIR := $(BUILDDIR)/apps/plugins/.picross
12PICRSCRS := $(wildcard $(PICRSCR_SRCDIR)/*.picross) 12PICRSCRS := $(wildcard $(PICRSCR_SRCDIR)/*.picross)
13 13
14#DUMMY := $(info [${PICRSCRS}]) 14#DUMMY := $(info [${PICRSCRS}])
@@ -18,7 +18,7 @@ DUMMY : all
18all: $(subst $(PICRSCR_SRCDIR)/,$(PICRSCR_BUILDDIR)/,$(PICRSCRS)) 18all: $(subst $(PICRSCR_SRCDIR)/,$(PICRSCR_BUILDDIR)/,$(PICRSCRS))
19 19
20$(PICRSCR_BUILDDIR)/%.picross: $(PICRSCR_SRCDIR)/%.picross | $(PICRSCR_BUILDDIR) 20$(PICRSCR_BUILDDIR)/%.picross: $(PICRSCR_SRCDIR)/%.picross | $(PICRSCR_BUILDDIR)
21 $(call PRINTS,CP $(subst $(PICRSCR_SRCDIR)/,,$<))cp $< $@ 21 $(call PRINTS,CP $(subst $(APPSDIR)/,,$<))cp $< $@
22 22
23$(PICRSCR_BUILDDIR): 23$(PICRSCR_BUILDDIR):
24 $(call PRINTS,MKDIR $@)mkdir -p $(PICRSCR_BUILDDIR)/ 24 $(call PRINTS,MKDIR $@)mkdir -p $(PICRSCR_BUILDDIR)/
diff --git a/apps/settings.h b/apps/settings.h
index 2277805fec..e3b11430cd 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -163,7 +163,7 @@ enum { SHOW_ALL, SHOW_SUPPORTED, SHOW_MUSIC, SHOW_PLAYLIST, SHOW_ID3DB,
163 163
164/* file and dir sort options */ 164/* file and dir sort options */
165enum { SORT_ALPHA, SORT_DATE, SORT_DATE_REVERSED, SORT_TYPE, /* available as settings */ 165enum { SORT_ALPHA, SORT_DATE, SORT_DATE_REVERSED, SORT_TYPE, /* available as settings */
166 SORT_ALPHA_REVERSED, SORT_TYPE_REVERSED }; /* internal use only */ 166 SORT_ALPHA_REVERSED, SORT_TYPE_REVERSED, SORT_AS_FILE }; /* internal use only */
167enum { SORT_INTERPRET_AS_DIGIT, SORT_INTERPRET_AS_NUMBER }; 167enum { SORT_INTERPRET_AS_DIGIT, SORT_INTERPRET_AS_NUMBER };
168 168
169/* recursive dir insert options */ 169/* recursive dir insert options */
diff --git a/apps/tree.c b/apps/tree.c
index 2e82b165af..58457c2d71 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -466,6 +466,13 @@ static int update_dir(void)
466 icon = tc.browse->icon; 466 icon = tc.browse->icon;
467 if (icon == NOICON) 467 if (icon == NOICON)
468 icon = filetype_get_icon(ATTR_DIRECTORY); 468 icon = filetype_get_icon(ATTR_DIRECTORY);
469 /* display sub directories in the title of plugin browser */
470 if (tc.dirlevel > 0 && *tc.dirfilter == SHOW_PLUGINS)
471 {
472 char *subdir = strrchr(tc.currdir, '/');
473 if (subdir)
474 title = subdir + 1; /* step past the separator */
475 }
469 } 476 }
470 else 477 else
471 { 478 {
@@ -1056,7 +1063,7 @@ int rockbox_browse(struct browse_context *browse)
1056 int last_context; 1063 int last_context;
1057 /* don't reset if its the same browse already loaded */ 1064 /* don't reset if its the same browse already loaded */
1058 if (tc.browse != browse || 1065 if (tc.browse != browse ||
1059 !(tc.currdir[1] && strcmp(tc.currdir, browse->root) == 0)) 1066 !(tc.currdir[1] && strstr(tc.currdir, browse->root) != NULL))
1060 { 1067 {
1061 tc.browse = browse; 1068 tc.browse = browse;
1062 tc.selected_item = 0; 1069 tc.selected_item = 0;
diff --git a/tools/buildzip.pl b/tools/buildzip.pl
index 2956b49492..59c32d3e3d 100755
--- a/tools/buildzip.pl
+++ b/tools/buildzip.pl
@@ -167,6 +167,13 @@ sub make_install {
167 glob_install("$src/rocks/$t/*", "$libdir/rocks/$t", "-m 0755"); 167 glob_install("$src/rocks/$t/*", "$libdir/rocks/$t", "-m 0755");
168 } 168 }
169 169
170 if(-e "$src/rocks/games/sgt_puzzles") {
171 unless (glob_mkdir("$libdir/rocks/games/sgt_puzzles")) {
172 return 0;
173 }
174 glob_install("$src/rocks/games/sgt_puzzles/*", "$libdir/rocks/games/sgt_puzzles", "-m 0755");
175 }
176
170 # rocks/viewers/lua 177 # rocks/viewers/lua
171 unless (glob_mkdir("$libdir/rocks/viewers/lua")) { 178 unless (glob_mkdir("$libdir/rocks/viewers/lua")) {
172 return 0; 179 return 0;
@@ -182,12 +189,13 @@ sub make_install {
182 #glob_mkdir("$temp_dir/rocks/demos/lua_scripts"); 189 #glob_mkdir("$temp_dir/rocks/demos/lua_scripts");
183 #glob_copy("$ROOT/apps/plugins/lua_scripts/*.lua", "$temp_dir/rocks/demos/lua_scripts/"); 190 #glob_copy("$ROOT/apps/plugins/lua_scripts/*.lua", "$temp_dir/rocks/demos/lua_scripts/");
184 } 191 }
185 #lua picross puzzles 192
193 #lua picross puzzles
186 if(-e "$ROOT/apps/plugins/picross") { 194 if(-e "$ROOT/apps/plugins/picross") {
187 unless (glob_mkdir("$libdir/rocks/games/picross")) { 195 unless (glob_mkdir("$libdir/rocks/games/.picross")) {
188 return 0; 196 return 0;
189 } 197 }
190 glob_install("$ROOT/apps/plugins/picross/*.picross", "$libdir/rocks/games/picross"); 198 glob_install("$ROOT/apps/plugins/picross/*.picross", "$libdir/rocks/games/.picross");
191 } 199 }
192 200
193 # all the rest directories 201 # all the rest directories
@@ -451,6 +459,12 @@ sub buildzip {
451 glob_copy("$ROOT/apps/plugins/lua_scripts/*.lua", "$temp_dir/rocks/demos/lua_scripts/"); 459 glob_copy("$ROOT/apps/plugins/lua_scripts/*.lua", "$temp_dir/rocks/demos/lua_scripts/");
452 } 460 }
453 461
462 #lua picross puzzles
463 if(-e "$ROOT/apps/plugins/picross") {
464 glob_mkdir("$temp_dir/rocks/games/.picross");
465 glob_copy("$ROOT/apps/plugins/picross/*.picross", "$temp_dir/rocks/games/.picross/");
466 }
467
454 # exclude entries for the image file types not supported by the imageviewer for the target. 468 # exclude entries for the image file types not supported by the imageviewer for the target.
455 my $viewers = "$ROOT/apps/plugins/viewers.config"; 469 my $viewers = "$ROOT/apps/plugins/viewers.config";
456 my $c="cat $viewers | gcc $cppdef -I. -I$firmdir/export -E -P -include config.h -"; 470 my $c="cat $viewers | gcc $cppdef -I. -I$firmdir/export -E -P -include config.h -";
@@ -512,7 +526,13 @@ sub buildzip {
512 foreach my $line (@rock_targetdirs) { 526 foreach my $line (@rock_targetdirs) {
513 if ($line =~ /([^,]*),(.*)/) { 527 if ($line =~ /([^,]*),(.*)/) {
514 my ($plugin, $dir)=($1, $2); 528 my ($plugin, $dir)=($1, $2);
515 move("$temp_dir/rocks/${plugin}.rock", "$temp_dir/rocks/$dir/${plugin}.rock"); 529 if($dir eq 'games' and substr(${plugin}, 0, 4) eq "sgt-") {
530 glob_mkdir("$temp_dir/rocks/$dir/sgt_puzzles");
531 move("$temp_dir/rocks/${plugin}.rock", "$temp_dir/rocks/$dir/sgt_puzzles/${plugin}.rock");
532 }
533 else {
534 move("$temp_dir/rocks/${plugin}.rock", "$temp_dir/rocks/$dir/${plugin}.rock");
535 }
516 if(-e "$temp_dir/rocks/${plugin}.ovl") { 536 if(-e "$temp_dir/rocks/${plugin}.ovl") {
517 # if there's an "overlay" file for the .rock, move that as 537 # if there's an "overlay" file for the .rock, move that as
518 # well 538 # well