[Lua] Npad Text Editor 08-05-2013, 09:09 AM
#1
Latest version: 0.54 (unstable)
Latest stable version: none
I quite like the way it is turning out except for many text/settings editing functions which I'm having tons of troubles with.
Some functionalities so far:
[*] Open new file/load file/save file/save copy/rename currently opened file
[*] Change font, font color, font size, window background color, textarea background color (you need to restart the program to see the changes)
[*] Drap 'n' drop files to open them
[*] Open files from CLI (wlua npad.wlua myfile.txt anotherfile.txt) (I made this to be able to add a "Edit with Npad" option in the Windows right click menu)
[*] Display current line/column position and number of total lines, words and characters
[*] Undo, redo, go back to last saved copy
[*] Find function finally working (only downwards)
[*] Replace function
[*] Convert tabs/spaces
Known bugs:
[*] Find function does not work properly when used to search upwards
[*] The whole settings thing isn't working properly
Todo:
[*] Improve find and replace functions by adding matching-text selection, find-next (F3) functions
note: text selection in Lua:
[*] Add a Select all option in the Edit menu
The default font used is Dejavu Sans Mono, which I'd recommend you to download in case you don't have it. If you don't have it, you could be viewing the textarea's text in Arial, or whatever (, I don't know), but you can change the font in the settings to whatever you like.
Here are the shortcuts (OS provided ones like CTRL + A in the textarea to select all are not included but are available, of course - the ones mentioned, like CTRL + Z to undo, have been replaced with custom functions instead):
The source code:
Lua version used: 5.1.
Please, report any bug/suggestion.
Latest stable version: none
I quite like the way it is turning out except for many text/settings editing functions which I'm having tons of troubles with.
Some functionalities so far:
[*] Open new file/load file/save file/save copy/rename currently opened file
[*] Change font, font color, font size, window background color, textarea background color (you need to restart the program to see the changes)
[*] Drap 'n' drop files to open them
[*] Open files from CLI (wlua npad.wlua myfile.txt anotherfile.txt) (I made this to be able to add a "Edit with Npad" option in the Windows right click menu)
[*] Display current line/column position and number of total lines, words and characters
[*] Undo, redo, go back to last saved copy
[*] Find function finally working (only downwards)
[*] Replace function
[*] Convert tabs/spaces
Known bugs:
[*] Find function does not work properly when used to search upwards
[*] The whole settings thing isn't working properly
Todo:
[*] Improve find and replace functions by adding matching-text selection, find-next (F3) functions
note: text selection in Lua:
Code:
iup.text.selection = "line,col:line,col"[*] Add a Select all option in the Edit menu
The default font used is Dejavu Sans Mono, which I'd recommend you to download in case you don't have it. If you don't have it, you could be viewing the textarea's text in Arial, or whatever (, I don't know), but you can change the font in the settings to whatever you like.
Here are the shortcuts (OS provided ones like CTRL + A in the textarea to select all are not included but are available, of course - the ones mentioned, like CTRL + Z to undo, have been replaced with custom functions instead):
Code:
CTRL + N New
CTRL + R Rename
CTRL + O Open
CTRL + S Save
ALT + S Save as
CTRL + P Save a copy
CTRL + Z Undo
CTRL + Y Redo
CTRL + F Find
CTRL + H Replace
F1 Help
F2 Shortcuts
F3 About
CTRL + Q QuitThe source code:
Code:
--------------------------------------------------------------------------------
-- --
-- Npad --
-- --
--------------------------------------------------------------------------------
-- --
-- You're allowed to edit and/or give away this code for free as long as you --
-- give credits. --
-- --
--------------------------------------------------------------------------------
-- --
-- npad · coded by noize · 2013 --
-- --
--------------------------------------------------------------------------------
require("iuplua")
require("iupluacontrols") -- needed for the color browser dialog
require("strbuf")
require("list")
require("socket")
local npad = {}
npad.version = "0.54"
npad.versioninfo = "(unstable)"
--------------------------------------------------------------------------------
-- custom alert function
-- like iup.Message() but uses an error dialog instead
--------------------------------------------------------------------------------
function alert(title,body,flag)
local dlg = iup.messagedlg {
dialogtype = flag,
title = title,
value = body
}
dlg:popup()
dlg:destroy()
end
--------------------------------------------------------------------------------
-- hotkeys
--------------------------------------------------------------------------------
npad.key = {}
npad.key.new = 590 -- CTRL + N
npad.key.ren = 594 -- CTRL + R
npad.key.open = 591 -- CTRL + O
npad.key.save = 595 -- CTRL + S
npad.key.saveas = 851 -- ALT + S
npad.key.savecopy = 592 -- CTRL + P
npad.key.undo = 602 -- CTRL + Z
npad.key.redo = 601 -- CTRL + Y
npad.key.backup = 578 -- CTRL + B
npad.key.copy = 579 -- CTRL + C
npad.key.cut = 600 -- CTRL + X
npad.key.paste = 598 -- CTRL + V
npad.key.find = 582 -- CTRL + F
npad.key.replace = 584 -- CTRL + H
npad.key.convert = 596 -- CTRL + T
npad.key.top = 642 -- CTRL + Arrow Up
npad.key.bottom = 648 -- CTRL + Arrow Down
npad.key.help = 143 -- F1
npad.key.shortcuts = 144 -- F2
npad.key.about = 145 -- F3
npad.key.quit = 593 -- CTRL + Q
--------------------------------------------------------------------------------
-- initialise file name, status, values, checks and settings
--------------------------------------------------------------------------------
npad.file = "untitled"
npad.backup = {}
npad.saved = 1
npad.font = "Dejavu Sans Mono"
npad.font_size = 10
npad.temp = {}
npad.settings = "npad.ini"
local f = io.open(npad.settings,"r")
if f then
for l in io.lines(npad.settings) do
local _, _, key, value = string.find(l, "(%a+)%s*=%s*(%a+)")
if value then
if key == "font-name" then
npad.font = value
elseif key == "font-color" then
npad.color = value
elseif key == "font-size" then
npad.font_size = value
elseif key == "textarea-background" then
npad.textbg = value
elseif key == "window-background" then
npad.background = value
elseif key == "tab-length" then
npad.tab_length = value
end
end
end
f:close()
end
--------------------------------------------------------------------------------
-- dialog elements
--------------------------------------------------------------------------------
npad.text = iup.multiline {
expand = "YES",
appendnewline = "NO",
tabsize = npad.tab_length,
size = "200x120"
}
if npad.color then
npad.text.fgcolor = npad.color
end
if npad.textbg then
npad.text.bgcolor = npad.textbg
end
npad.text.font = npad.font .. " , " .. npad.font_size
npad.tot = {}
npad.line = 1
npad.column = 1
npad.tot.ln = 1
npad.tot.words = 0
npad.tot.chars = 0
npad.pos = iup.label {
title = "Ln " .. npad.line ..
" Col " .. npad.column ..
" | Ln " .. npad.tot.ln ..
" Wrd " .. npad.tot.words ..
" Ch " .. npad.tot.chars,
tip = "[current line] | [whole file]",
size = "300x"
}
npad.line = 1
npad.n = 0
if npad.background then
for i in string.gmatch(npad.background,"%S+") do
npad.n = npad.n + i
end
if npad.n < (40 * 3) then
npad.pos.fgcolor = "255 255 255"
end
end
--------------------------------------------------------------------------------
-- file handling
--------------------------------------------------------------------------------
function npad.close()
if npad.unsaved then
local choice
if npad.file:len() > 16 then
choice = iup.Alarm("Npad - unsaved changes","Do you want to save the changes made to\n" .. npad.file .. "?","Yes","No","Cancel")
else
choice = iup.Alarm("Npad - unsaved changes","Do you want to save the changes made to " .. npad.file .. "?","Yes","No","Cancel")
end
if choice == 1 then
save()
elseif choice == 3 then
iup.MainLoop()
end
end
end
function new()
npad.close()
npad.text.value = ""
npad.wnd.title = "Npad"
npad.file = "untitled"
npad.latest = npad.wnd.title
npad.backup = {}
npad.saved = 1
npad.unsaved = false
end
function ren()
if not npad.saved then
alert("Npad - rename","No file currently opened","INFORMATION")
return
end
local dlg = iup.filedlg {
dialogtype = "SAVE",
title = "Npad - Rename currently opened file",
nochangedir = "NO",
directory = npad.lastdir,
filter = "*.*",
filterinfo = "All files",
allownew = "YES",
}
dlg:popup(iup.LEFT, iup.LEFT)
local status = dlg.status
local curf = npad.file
npad.file = dlg.value
npad.lastdir = dlg.directory
npad.wnd.title = "Npad - " .. npad.file
dlg:destroy()
if status ~= "-1" then
if not npad.file then
alert("Npad","Failed to save to file " .. npad.file , "ERROR")
return
end
os.rename(curf,npad.file)
end
end
function npad.load(lfile)
if not lfile then return nil end
local f = io.open(lfile, "r")
if not f then
alert("Npad","Failed to load file " .. lfile , "ERROR")
return
else
npad.text.value = f:read("*a")
f:close()
npad.file = lfile
npad.wnd.title = "Npad - " .. npad.file
npad.saved = true
npad.backup = npad.text.value
if npad.file:find("\\") then
npad.tempf = string.split(npad.file,"\\")
elseif npad.file:find("/") then
npad.tempf = string.split(npad.file,"/")
else
npad.lastdir = "."
npad.tempf = nil
end
if npad.tempf then
table.remove(npad.tempf,#npad.tempf)
npad.lastdir = table.concat(npad.tempf,"/")
end
end
end
function open()
local dlg = iup.filedlg {
dialogtype = "OPEN",
title = "Npad - Load file",
nochangedir = "NO",
directory = npad.lastdir,
filter = "*.*",
filterinfo = "All Files",
allownew = "NO",
}
dlg:popup(iup.CENTER, iup.CENTER)
local lfile = dlg.value
local status = dlg.status
npad.file = lfile
npad.lastdir = dlg.directory
dlg:destroy()
if status == 1 then
alert("Npad","Failed to load file " .. lfile , "ERROR")
return
elseif status ~= -1 then
npad.load(lfile)
end
npad.latest = npad.wnd.title
npad.backup = {}
npad.saved = 1
npad.unsaved = false
end
function save()
if not npad.unsaved then
local f = io.open(npad.file, "w")
if f then
f:write(npad.text.value)
f:close()
npad.latest = npad.text.value
npad.unsaved = false
else
alert("Npad","Failed to save file " .. npad.file , "ERROR")
return
end
else
saveas()
end
end
function saveas()
local dlg = iup.filedlg {
dialogtype = "SAVE",
title = "Npad - Save file",
nochangedir = "NO",
directory = npad.lastdir,
filter = "*.*",
filterinfo = "All files",
allownew = "YES",
}
dlg:popup(iup.LEFT, iup.LEFT)
local status = dlg.status
npad.file = dlg.value
npad.lastdir = dlg.directory
dlg:destroy()
if status ~= "-1" then
if not npad.file then
alert("Npad","Failed to save to file " .. npad.file , "ERROR")
return
end
local f = io.open(npad.file, "w")
if f then
f:write(npad.text.value)
f:close()
npad.latest = npad.text.value
npad.unsaved = false
npad.wnd.title = "Npad - " .. npad.file
else
alert("Npad","Failed to write to file " .. npad.file , "ERROR")
end
end
end
function savecopy()
local dlg = iup.filedlg {
dialogtype = "SAVE",
title = "Npad - Save copy",
nochangedir = "NO",
directory = npad.lastdir,
filter = "*.*",
filterinfo = "All files",
allownew = "YES",
}
dlg:popup(iup.LEFT, iup.LEFT)
local status = dlg.status
local file = dlg.value
npad.lastdir = dlg.directory
dlg:destroy()
if status ~= "-1" then
if not file then
alert("Npad","Failed to save to file " .. file , "ERROR")
return
end
local f = io.open(file, "w")
if f then
f:write(npad.text.value)
f:close()
npad.latest = npad.text.value
npad.unsaved = false
else
alert("Npad","Failed to write to file " .. file , "ERROR")
end
end
end
function quit()
npad.close()
os.exit()
end
--------------------------------------------------------------------------------
-- text editing functions
--------------------------------------------------------------------------------
function undo()
local pos = npad.text.caret
npad.saved = npad.saved - 1
npad.text.value = npad.backup[npad.saved]
npad.text.caret = pos
end
function redo()
if npad.saved < #npad.backup then
local pos = npad.text.caret
npad.saved = npad.saved + 1
npad.text.value = npad.backup[npad.saved]
npad.text.caret = pos
end
end
function backup()
npad.text.value = npad.latest
end
function copy()
npad.text.clipboard = "COPY"
end
function cut()
npad.text.clipboard = "CUT"
end
function paste()
npad.text.clipboard = "PASTE"
end
function remove()
npad.text.clipboard = "CLEAR"
end
function find()
local match = {}
function found(l)
iup.Message("Npad - Line " .. npad.temp, l)
match.found = true
end
local findBox = iup.text {expand = "HORIZONTAL"}
local down = iup.toggle {title = "Down"}
local top = iup.toggle {title = "Down from top"}
local up = iup.toggle {title = "Up"}
local bottom = iup.toggle {title = "Up from bottom"}
local ok = iup.button {
title = "Ok",
size = "35x",
action = function ()
if (findBox.value == "" or not npad.text.value:find(findBox.value)) then
return
end
local lines = npad.text.value:split("\n")
if down.value == "ON" or top.value == "ON" then
npad.temp = 1
for k,l in pairs(lines) do
if l:find(findBox.value) then
if top.value == "ON" then -- down from top
found(l)
break
elseif npad.line < npad.temp then -- if direction is "down" take only lines beneath current line
found(l)
break
end
end
npad.temp = npad.temp + 1
end
else
npad.temp = #lines
for k,l in pairs(table.sort(lines,function(x,y) return x > y end)) do
if l:find(findBox.value) then
if bottom.value == "ON" then -- up from bottom
found(l)
break
elseif npad.line > npad.temp then -- if direction is "up" take only lines above current line
found(l)
break
end
end
npad.temp = npad.temp - 1
end
end
if not match.found then
alert("Npad - no matches found","No results for your search\nTry changing searching direction","INFORMATION")
end
end
}
local cancel = iup.button {
title = "Cancel",
size = "50x",
action = function ()
close()
end
}
local dlg = iup.dialog {
iup.vbox {
iup.hbox {
margin = "3x3",
iup.label {title = "Find: "},
findBox,
gap = 3
},
iup.hbox {
margin = "3x3",
iup.label {title = "Direction: "},
iup.radio {
iup.vbox {
iup.hbox {
down,
top,
gap = 15
},
iup.hbox {
up,
bottom,
gap = 31
},
margin = "3x0"
}
}
},
iup.hbox {
iup.fill {},
ok,
cancel,
iup.fill {}
}
},
defaultenter = ok,
title = "Npad - Find",
margin = "2x2",
size = "250x",
topmost = "YES"
}
function close()
dlg:destroy()
end
dlg:showxy(iup.CENTER,iup.CENTER)
iup.MainLoop()
end
function replace()
local textbox = iup.text {expand = "HORIZONTAL"}
local replace = iup.text {expand = "HORIZONTAL"}
local toggle = {}
toggle[1] = iup.toggle {title = "Escape sequences", tip = "Accepted sequences are \"\\n\" and \"\\t\"", value = "ON"}
toggle[2] = iup.toggle {title = "Escape sequences", tip = "Accepted sequences are \"\\n\" and \"\\t\"", value = "ON"}
local ok = iup.button {
title = "Ok",
size = "35x",
action = function ()
local text = {}
text[1] = textbox.value
text[2] = replace.value
for i = 1, #toggle do
if toggle[i].value == "ON" then
text[i] = text[i]:gsub("\\n","\n")
text[i] = text[i]:gsub("\\t","\t")
end
end
npad.text.value = npad.text.value:gsub(text[1],text[2])
end
}
local cancel = iup.button {
title = "Cancel",
size = "50x",
action = function ()
close()
end
}
local dlg = iup.dialog {
iup.vbox {
iup.hbox {
iup.label {title = "Replace: "},
textbox,
toggle[1],
gap = 3
},
iup.hbox {
iup.label {title = "With: "}, -- a more elegant solution, using gap or margin would hardly fit the look this well
replace,
toggle[2],
gap = 3
},
iup.hbox {
iup.fill {},
ok,
cancel,
iup.fill {}
},
},
defaultenter = ok,
title = "Npad - Replace",
margin = "2x2",
size = "250x",
topmost = "YES"
}
function close()
dlg:destroy()
end
dlg:showxy(iup.CENTER,iup.CENTER)
iup.MainLoop()
end
function convert()
local ok, choice = iup.GetParam("Npad", nil, "Convert: %l|Tabs to spaces|Spaces to tabs|\n", 0)
if ok then
if choice == 0 then
local ok, times = iup.GetParam("Npad - Tabs to spaces", nil, "Number of spaces: %i\n", 4)
if ok then
local ws = " "
npad.text.value = npad.text.value:gsub("\t",ws:rep(times))
end
elseif choice == 1 then
local ok, times = iup.GetParam("Npad - Spaces to tabs", nil, "Number of spaces: %i\n", 4)
if ok then
local ws = " "
npad.text.value = npad.text.value:gsub(ws:rep(times),"\t")
end
end
end
end
function top()
npad.text.value = npad.text.value
end
function bottom()
npad.text.append = ""
end
--------------------------------------------------------------------------------
-- settings
--------------------------------------------------------------------------------
function npad.set(obj,value)
local o = obj:gsub("%%%-","%_")
npad[o] = value
npad.text[o] = npad[o]
npad.temp = {}
local f = io.open(npad.settings,"r")
if f then -- if the file exists and is readable
local cont = f:read("*a")
if string.find(cont,obj) then -- if the element is already defined in the file
for l in io.lines(npad.settings) do -- parse each line
if l:find(obj) and l:find("%=") then -- if any line defines the element
table.insert(npad.temp,obj .. " = " .. npad[o]) -- redefine it
else -- if the current line does not define the element
table.insert(npad.temp,l) -- keep it as it is
end
end
npad.setflag = "w"
else -- if the element is not defined yet in the file
npad.temp = {obj .. " = " .. npad[o]}
npad.setflag = "a"
end
f:close()
else -- no file exists, or it is not readable
npad.temp = {obj .. " = " .. npad[o]}
npad.setflag = "w"
end
local f = io.open(npad.settings,npad.setflag)
if f then
f:write(string.gsub(table.concat(npad.temp,"\n"),"%%","") .. "\n")
f:close()
local f = io.open("temp.lua","w")
f:write("dofile(\"" .. arg[0] .. "\")")
f:close()
npad.wnd.hidetaskbar = "YES"
dofile("temp.lua")
else
alert("Npad","Failed to save settings to file " .. npad.settings , "ERROR")
end
end
function font()
local textbox = iup.text {value = npad.font, expand = "HORIZONTAL",}
local ok = iup.button {title = "Ok", size = "40x",}
local apply = iup.button {title = "Apply", size = "40x",}
local cancel = iup.button {title = "Cancel", size = "40x",}
local dlg = iup.dialog {
iup.vbox {
iup.hbox {
iup.label {title = "Font:", size = "30x",},
textbox,
gap = "5",
},
iup.hbox {
iup.fill{},
ok,
apply,
cancel,
iup.fill{},
},
margin = "2x2",
},
defaultenter = ok,
defaultesc = cancel,
size = "200x50",
title = "Font settings",
topmost = "YES"
}
function ok:action()
npad.set("font%-name",textbox.value)
dlg:destroy()
end
function apply:action()
npad.set("font%-name",textbox.value)
end
function cancel:action()
dlg:destroy()
end
dlg:show()
end
function font_size()
local ok, value = iup.GetParam("Npad", nil, "Font size: %i\n", npad.font_size)
if ok ~= 0 and value then
npad.set("font%-size",value)
end
end
function color(element)
if element == "font%-color" then
npad.e = "color"
elseif element == "textarea%-background" then
npad.e = "textbg"
elseif element == "window%-background" then
npad.e = "background"
end
if npad[npad.e] then
npad.temp.split = string.split(npad[npad.e]," ")
else
npad.temp.split = {255,255,255}
end
local r, g, b = iup.GetColor(iup.CENTER, iup.CENTER, npad.temp.split[1], npad.temp.split[2], npad.temp.split[3])
if r then
local color = r .. " " .. g .. " " .. b
npad.set(element,color)
npad.textbg = color
npad.wnd:popup()
end
end
function tab_length()
local ok, value = iup.GetParam("Npad", nil, "Tab length: %i\n", npad.tab_length)
if ok ~= 0 and value then
npad.set("tab%-length",value)
npad.text.tabsize = value
end
end
function default(obj)
npad.set(obj,"")
end
--------------------------------------------------------------------------------
-- help functions
--------------------------------------------------------------------------------
function help()
alert("Gimme time","This is supposed to be the beta version, so calm down","ERROR")
-- toadd:
-- font suggestions in case of lack of installation of default font
end
function shortcuts()
alert("Mh-mh","This is supposed to be the beta version, so calm down","ERROR")
end
function about()
alert("Well","If this is not anymore the beta version, and I still haven't written this function, feel free to get upset","ERROR")
end
function version()
alert("Npad - " .. npad.version , "Current version is " .. npad.version .. " " .. npad.versioninfo,"INFORMATION")
end
function updatescheck()
local s = socket.connect("www.intosec.org",80)
if not s then
alert("Npad - Error","You need an internet connection to check for updates","ERROR")
return
end
s:send("GET /index.php/topic,549.msg1459.html HTTP/1.0\r\nUser-Agent: Npad/1337\r\n\r\n")
while true do
local data, status, partial = s:receive(1024)
local data = data or partial
if data:find(" version: ") then
local split = data:split("Latest version: ")
local split = split[2]:split("%)")
local latest = split[1] .. ")"
local split = data:split("Latest stable version: ")
local split = split[2]:split("<")
local stable = split[1]
alert(
"Npad - Check for updates",
"Current version is " .. npad.version .. " " .. npad.versioninfo .. "\n" ..
"Latest version release is " .. latest .. "\n" ..
"Latest stable release is " .. stable .. "\n\n" ..
"You can download the most recent versions here:\nwww.intosec.org/index.php/topic,549.msg1459.html",
"INFORMATION"
)
end
if status == "closed" then break end
end
s:close()
end
--------------------------------------------------------------------------------
-- main dialog objects
--------------------------------------------------------------------------------
npad.vbox = iup.vbox {
iup.vbox {
npad.text,
iup.hbox {
npad.pos,
margin = "1x-13",
},
},
margin = "3x3",
gap = "17",
}
npad.menu = iup.menu {
iup.submenu {
title = "&File", -- the "&" character identifies the ALT hotkey character
iup.menu {
iup.item {
title = "&New\tCTRL + N",
action = "new()",
},
iup.item {
title = "&Rename...\tCTRL + R",
action = "ren()",
},
iup.item {
title = "&Open...\tCTRL + O",
action = "open()",
},
iup.item {
title = "&Save\tCTRL + S",
action = "save()",
},
iup.item {
title = "S&ave as...\tALT + S",
action = "saveas()",
},
iup.item {
title = "Save a ©...\tCTRL + P",
action = "savecopy()",
},
iup.separator{},
iup.item {
title = "E&xit\tCTRL + Q",
action = "quit()",
},
},
},
iup.submenu {
title = "&Edit",
iup.menu {
iup.item {
title = "&Undo\tCTRL + Z",
action = "undo()",
},
iup.item {
title = "&Redo\tCTRL + Y",
action = "redo()",
},
iup.item {
title = "&Backup\tCTRL + B",
action = "backup()",
},
iup.separator {},
iup.item {
title = "&Copy\tCTRL + C",
action = "copy()",
},
iup.item {
title = "Cut\tCTRL + &X",
action = "cut()",
},
iup.item {
title = "&Paste\tCTRL + V",
action = "paste()",
},
iup.item {
title = "&Remove\tDEL",
action = "remove()",
},
iup.separator {},
iup.item {
title = "&Find\tCTRL + F",
action = "find()",
},
iup.item {
title = "&Replace\tCRTL + H",
action = "replace()",
},
iup.separator {},
iup.item {
title = "Convert &tabs/spaces\tCTRL + T",
action = "convert()",
},
iup.separator {},
iup.item {
title = "Go to top\tCTRL + Arrow Up",
action = "top()",
},
iup.item {
title = "Go to bottom\tCTRL + Arrow Down",
action = "bottom()",
}
},
},
iup.submenu {
title = "Se&ttings",
iup.menu {
iup.submenu {
title = "&Text",
iup.menu {
iup.item {
title = "&Font",
action = "font()",
},
iup.item {
title = "&Size",
action = "font_size()",
},
iup.item {
title = "&Color",
action = "color('font%-color')",
},
},
},
iup.submenu {
title = "&Background",
iup.menu {
iup.item {
title = "&Textarea",
action = "color('textarea%-background')",
},
iup.item {
title = "&Window",
action = "color('window%-background')",
},
},
},
iup.submenu {
title = "&Default",
iup.menu {
iup.submenu {
title = "&Text",
iup.menu {
iup.item {
title = "&Font",
action = "default('font')",
},
iup.item {
title = "&Size",
action = "default('font%-size')",
},
iup.item {
title = "&Color",
action = "default('color')",
},
},
},
iup.submenu {
title = "&Background",
iup.menu {
iup.item {
title = "&Textarea",
action = "default('textarea%-background')",
},
iup.item {
title = "&Window",
action = "default('window%-background')",
},
},
},
},
},
},
},
iup.submenu {
title = "&Help",
iup.menu {
iup.item {
title = "&Help\tF1",
action = "help()",
},
iup.item {
title = "&Shortcuts\tF2",
action = "shortcuts()",
},
iup.item {
title = "&About\tF3",
action = "about()",
},
iup.separator {},
iup.item {
title = "&Version",
action = "version()",
},
iup.item {
title = "&Check for updates",
action = "updatescheck()",
},
},
},
}
npad.wnd = iup.dialog {
npad.vbox,
title = "Npad",
menu = npad.menu,
dragdrop = "YES",
size = "440x200"
}
if npad.background then
npad.wnd.background = npad.background
end
--------------------------------------------------------------------------------
-- event-driven functions
--------------------------------------------------------------------------------
function npad.text:k_any(key) -- when any key is pressed in the textarea
if npad.text.value ~= npad.backup[npad.saved] then
npad.saved = npad.saved + 1
npad.backup[npad.saved] = npad.text.value
end
for k,v in pairs(npad.key) do
if key == npad.key[k] then
loadstring(k .. "()")()
return iup.IGNORE
end
end
end
function npad.text:caret_cb(line, column) -- on cursor move in textarea
if npad.text.value ~= npad.latest then -- if text is different from the last saved text
npad.wnd.title = "Npad * " .. npad.file -- unsaved changes
npad.unsaved = true
else
npad.wnd.title = "Npad - " .. npad.file -- no unsaved changes
npad.unsaved = false
end
npad.tot.words = 0
npad.tot.chars = 0
npad.tot.ln = #npad.text.value:split("\n")
for w in npad.text.value:gmatch("%S+") do
npad.tot.words = npad.tot.words + 1
end
for w in npad.text.value:gmatch(".") do
if w ~= "\n" then
npad.tot.chars = npad.tot.chars + 1
end
end
npad.line = line
npad.column = column
npad.pos.title = "Ln " .. npad.line ..
" Col " .. npad.column ..
" | Ln " .. npad.tot.ln ..
" Wrd " .. npad.tot.words ..
" Ch " .. npad.tot.chars -- update cursor position
end
function npad.wnd:dropfiles_cb(file, n, x, y) -- drag 'n' drop files wherever on the dialog
if n == 0 then -- open only the first file
npad.load(file)
end
end
function npad.wnd:close_cb() -- on dialog close
quit()
end
--------------------------------------------------------------------------------
-- show the dialog
--------------------------------------------------------------------------------
npad.wnd:show()
iup.SetFocus(npad.text)
if arg[1] then npad.load(arg[1]) end
if arg[2] then
for i = 2, #arg do
os.execute("lua " .. arg[0] .. " " .. arg[i])
end
end
iup.MainLoop()Lua version used: 5.1.
Please, report any bug/suggestion.
My Bitcoin address: 1AtxVsSSG2Z8JfjNy9KNFDUN6haeKr7LiP
Give me money by visiting www.google.com here: http://coin-ads.com/6Ol83U
If you want a Bitcoin URL shortener/advertiser, please, use this referral: http://coin-ads.com/register.php?refid=noize
Give me money by visiting www.google.com here: http://coin-ads.com/6Ol83U
If you want a Bitcoin URL shortener/advertiser, please, use this referral: http://coin-ads.com/register.php?refid=noize


![[+]](https://sinister.li/images/modern/collapse_collapsed.png)