-- license:BSD-3-Clause -- copyright-holders:Carl -- use plugin options to save the input port list to a gettext formatted file -- the file is saved in the ctrlrpath dir -- use #import to load names from a different file -- use #set ,,... to override names for a child set, common names should be listed at the top before any #set tags local exports = {} exports.name = "portname" exports.version = "0.0.1" exports.description = "IOPort name/translation plugin" exports.license = "The BSD 3-Clause License" exports.author = { name = "Carl" } local portname = exports function portname.startplugin() local ctrlrpath = lfs.env_replace(manager:options().entries.ctrlrpath:value():match("([^;]+)")) local function get_filename(nosoft) local filename if emu.softname() ~= "" and not nosoft then filename = emu.romname() .. "_" .. emu.softname() .. ".po" else filename = emu.romname() .. ".po" end return filename end emu.register_start(function() local reclevel = 0 local function parse_names(names) local orig, rep local setfound = true reclevel = reclevel + 1 if reclevel == 3 then emu.print_verbose("portname: too many import levels\n") return end names:gsub("[^\n\r]*", function (line) if line:find("^#import") then local impfile = emu.file(ctrlrpath .. "/portname", "r") local ret = impfile:open(line:match("^#import (.*)")) if ret then emu.print_verbose("portname: import file not found\n") else parse_names(impfile:read(impfile:size())) end elseif line:find("^#set") then local sets = line:match("^#set (.*)") setfound = false for s in sets:gmatch("[^,]*") do if s == emu.romname() then setfound = true break end end elseif line:find("^msgid") then orig = line:match("^msgid \"(.+)\"") elseif line:find("^msgstr") then rep = line:match("^msgstr \"(.+)\"") if rep and rep ~= "" and setfound then rep = rep:gsub("\\(.)", "%1") orig = orig:gsub("\\(.)", "%1") for pname, port in pairs(manager:machine():ioport().ports) do if port.fields[orig] then port.fields[orig].live.name = rep end end end end return line end) reclevel = reclevel - 1 end local file = emu.file(ctrlrpath .. "/portname", "r") local ret = file:open(get_filename()) if ret then ret = file:open(get_filename(true)) if ret then ret = file:open(manager:machine():system().parent .. ".po") if ret then return end end end parse_names(file:read(file:size())) end) local function menu_populate() return {{ _("Save input names to file"), "", 0 }} end local function menu_callback(index, event) if event == "select" then local fields = {} for pname, port in pairs(manager:machine():ioport().ports) do for fname, field in pairs(port.fields) do local dname = field.default_name if not fields[dname] then fields[dname] = {} fields[dname].name = "" end if fname ~= dname then fields[dname].name = fname end fields[dname].port = pname fields[dname].mask = field.mask fields[dname].default = dname end end local function check_path(path) local attr = lfs.attributes(path) if not attr then lfs.mkdir(path) if not lfs.attributes(path) then manager:machine():popmessage(_("Failed to save input name file")) emu.print_verbose("portname: unable to create path " .. path .. "\n") return false end elseif attr.mode ~= "directory" then manager:machine():popmessage(_("Failed to save input name file")) emu.print_verbose("portname: path exists but isn't directory " .. path .. "\n") return false end return true end if not check_path(ctrlrpath) then return false end if not check_path(ctrlrpath .. "/portname") then return false end local filename = get_filename() local file = io.open(ctrlrpath .. "/portname/" .. filename, "r") if file then emu.print_verbose("portname: input name file exists " .. filename .. "\n") manager:machine():popmessage(_("Failed to save input name file")) file:close() return false end local sfields = {} for def, field in pairs(fields) do sfields[#sfields + 1] = field end table.sort(sfields, function(a, b) if(a.port == b.port) then return a.mask < b.mask end return a.port < b.port end) file = io.open(ctrlrpath .. "/portname/" .. filename, "w") for n, field in ipairs(sfields) do def = field.default:gsub("[\\\"]", function (s) return "\\" .. s end) custom = field.name:gsub("[\\\"]", function (s) return "\\" .. s end) file:write(string.format("# port %s mask %08x\n", field.port, field.mask)) file:write("msgid \"" .. def .."\"\nmsgstr \"" .. custom .. "\"\n\n") end file:close() manager:machine():popmessage(string.format(_("Input port name file saved to %s"), ctrlrpath .. "/portname/" .. filename)) end return false end emu.register_menu(menu_callback, menu_populate, _("Input ports")) end return exports