summaryrefslogtreecommitdiff
path: root/Master/tlpkg/tlpsv/psv.wx.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/tlpkg/tlpsv/psv.wx.lua')
-rw-r--r--Master/tlpkg/tlpsv/psv.wx.lua2181
1 files changed, 2181 insertions, 0 deletions
diff --git a/Master/tlpkg/tlpsv/psv.wx.lua b/Master/tlpkg/tlpsv/psv.wx.lua
new file mode 100644
index 00000000000..4c8461f8735
--- /dev/null
+++ b/Master/tlpkg/tlpsv/psv.wx.lua
@@ -0,0 +1,2181 @@
+--[[----------------------------------------------------------------------------
+-- PS_View -- previewing utility for Ghostscript interpreter
+-- Authors: P. Strzelczyk, P. Pianowski. Created: 15.06.1993; Lua part 26.10.2007
+-- Address: BOP s.c. Gen. T. Bora-Komorowskiego 24, 80-377 Gda\'nsk, Poland
+-- bop@bop.com.pl
+-- Copyright: (c) 2008 BOP s.c.
+-- Licence: GPL
+-- Current version: 5.05; 26.04.2008
+--
+-- 4.95 -- first working version of Lua engine
+-- 4.96 -- mouse interface added (and many other changes)
+-- 4.97 -- file search, open dialog, first approach of refresh, and icons
+-- 4.98 -- new callbacks added: CONSOLE, CONFIG, INFO, console is now always
+-- available (maybe hidden), more file search changes
+-- 5.00 -- files renamed, refresh added, all dialogs active
+-- 5.01 -- `namespaces': gsobj, gswin, gsargs, gsstat added, internal timer
+-- functions rebuild, mouse pane and scroll functionality implemented
+-- refresh/update functionality fully implemented
+-- 5.02 -- erase_event neutralised, DSC events isolated, RETURN = next page
+-- 5.03 -- first attempt of localisation, grids on separate `layer'
+-- 5.04 -- DSC reading corrected, `layer' and updating image corrected
+-- 5.05 -- post-Pingwinaria release, 'layer' and printing bug corrected
+-- 5.06 -- BachoTeX release
+------------------------------------------------------------------------------]]
+
+local PS_VIEW_NAME="PS_View"
+local PS_VIEW_VERSION=5.06
+local PS_VIEW_VERSION_STRING -- defined later, after locale loading
+local PSV_GsPars = {"-dNOPAUSE","-dDELAYBIND","-dNOEPS"}
+
+local frame, console = nil, nil
+
+local gsobj={
+ instancechecker = nil,
+ gsdll = nil,
+ config = nil,
+ locale = nil,
+ ghostscript = nil,
+ image = nil,
+ gstimer = nil,
+ dscthread = nil,
+ dialog = nil,
+ menu = nil,
+ SBsty = {},
+ SBall = {},
+ overlay = nil,
+ bbmp = nil,
+ obmp = nil,
+}
+
+local gswin={
+ gswindow = nil,
+ logwindow = nil,
+ editwindow = nil,
+ menuBar = nil,
+ statusBar = nil,
+ dialog = nil,
+}
+
+local gsargs = {
+ args= {}, -- arguments to ghostscript (wihout paths)
+ dllloc= "", -- localisation of DLL (passed to wxGhostscript)
+ libloc = "", -- search path for Postscript files (passed to wxGhostscript,
+ -- mounted from gslib, libs and psvlib)
+ fontloc = "", -- search path for fonts (passed to wxGhostscript)
+ libs= {}, -- list of paths setted by -i option
+ gslib= "", -- path to GS init files (from config file or discovered from dllloc)
+ psvlib= "", -- path to PS_View files (from config file or discovered from
+ -- paths in progs or path to this program -- arg[0])
+ progs = {}, -- PostScript program to run during init (added at the end of args)
+ dftpars = PSV_GsPars, -- default GS arguments (can be overriden by config file,
+ -- added ath the begin of args)
+ psf_dir = "", -- directory with the curently opened file
+ psf_name = "", -- name of the curently opened file
+}
+local psvpars = {
+ cmd_pars = "",
+ language = "",
+}
+local gsstat = {
+ refr_int = 0,
+ refresh = 0,
+ update = 0,
+ working = false,
+ ready = false,
+ inoverlay= false,
+ drawoverlay= false,
+}
+
+function MakeIcons()
+ local psvimg_xpm = {
+ "48 48 3 1",
+ "@ c black",
+ ". c yellow",
+ " c None",
+ " @@@@@@ ",
+ " @....@@@ ",
+ " @.......@ ",
+ " @........@@ ",
+ " @..........@ ",
+ " @...........@ ",
+ " @............@ ",
+ " @..............@ ",
+ " @...............@ ",
+ " @................@ ",
+ " @..................@ ",
+ " @....................@ ",
+ " @......................@ ",
+ " @........................@ ",
+ " @..........................@ ",
+ " @............................@@ ",
+ " @...............................@@ ",
+ " @..................................@@@@@@",
+ " @........................................@",
+ " @.........................................@",
+ " @......@@@@@@@@@....@@@@@..@@@@..@@@@@.....@",
+ " @.......@@@@@@@@@@..@@@@@@@.@@@@..@@@@@.....@",
+ " @........@@@@@@@@@@@.@@@..@@.@@@@..@@@@@.....@",
+ " @..........@@@...@@@.@@@@.....@@....@@@.....@ ",
+ " @...........@@@....@@..@@@@@...@@...@@@......@ ",
+ "@@...........@@@....@@....@@@@..@@@.@@@......@ ",
+ "@............@@@...@@@.@@..@@@...@@@@@.......@ ",
+ "@............@@@@@@@@..@@@@@@@...@@@@.......@ ",
+ "@............@@@@@@@....@@@@@.....@@.......@ ",
+ "@............@@@..........................@ ",
+ "@@@@@@......@@@@@........................@ ",
+ " @@....@@@@@.......................@ ",
+ " @@..@@@@@......................@ ",
+ " @...........................@ ",
+ " @.........................@ ",
+ " @.......................@ ",
+ " @.....................@ ",
+ " @...................@ ",
+ " @.................@ ",
+ " @...............@ ",
+ " @...............@ ",
+ " @.............@ ",
+ " @............@ ",
+ " @..........@ ",
+ " @@........@ ",
+ " @.......@ ",
+ " @@.....@ ",
+ " @@@@@@ "
+ };
+
+ local psvimg_xpm32 = {
+ "32 32 3 1",
+ "@ c black",
+ ". c yellow",
+ " c None",
+ " @@@@@ ",
+ " @....@@ ",
+ " @......@ ",
+ " @.......@ ",
+ " @.........@ ",
+ " @..........@ ",
+ " @............@ ",
+ " @..............@ ",
+ " @................@ ",
+ " @..................@ ",
+ " @....................@@ ",
+ " @.......................@@@@",
+ " @...........................@",
+ " @....@@@@@@...@@@@.@@@..@@@..@",
+ " @.....@@@@@@@.@@..@.@@@..@@@..@",
+ " @......@@..@@.@@@....@...@@...@",
+ "@.......@@..@@..@@@@..@@.@@...@ ",
+ "@.......@@.@@@.@...@@.@@@@...@ ",
+ "@.......@@@@@..@@@@@@..@@...@ ",
+ "@.......@@......@@@@...@@..@ ",
+ "@@@....@@@@...............@ ",
+ " @@..@@@@..............@ ",
+ " @..................@ ",
+ " @@...............@ ",
+ " @.............@ ",
+ " @...........@ ",
+ " @..........@ ",
+ " @........@ ",
+ " @.......@ ",
+ " @......@ ",
+ " @@....@ ",
+ " @@@@@ "
+ };
+
+ local psvimg_xpm16 = {
+ "16 16 3 1",
+ "@ c black",
+ ". c yellow",
+ " c None",
+ " @@@ ",
+ " @..@ ",
+ " @...@ ",
+ " @.....@ ",
+ " @.......@ ",
+ " @.........@ ",
+ " @...........@@",
+ " @..@@@.@@@@.@.@",
+ "@...@.@.@@.@.@.@",
+ "@...@@@@@@.@@..@",
+ "@@@.@.........@ ",
+ " @.........@ ",
+ " @.......@ ",
+ " @.....@ ",
+ " @...@ ",
+ " @@@@ "
+ };
+
+ local psvtxt_xpm = {unpack(psvimg_xpm)}
+ psvtxt_xpm[3]=". c green"
+
+ local psvtxt_xpm32 = {unpack(psvimg_xpm32)}
+ psvtxt_xpm32[3]=". c green"
+
+ local psvtxt_xpm16 = {unpack(psvimg_xpm16)}
+ psvtxt_xpm16[3]=". c green"
+
+ local bmpi,iconi,iconimg,icontxt
+
+ iconi = wx.wxIcon()
+ bmpi = wx.wxBitmap(psvimg_xpm)
+ iconi:CopyFromBitmap(bmpi)
+ iconimg = wx.wxIconBundle(iconi)
+ bmpi = wx.wxBitmap(psvimg_xpm32)
+ iconi:CopyFromBitmap(bmpi)
+ iconimg:AddIcon(iconi)
+ bmpi = wx.wxBitmap(psvimg_xpm16)
+ iconi:CopyFromBitmap(bmpi)
+ iconimg:AddIcon(iconi)
+
+ bmpi = wx.wxBitmap(psvtxt_xpm)
+ iconi:CopyFromBitmap(bmpi)
+ icontxt = wx.wxIconBundle(iconi)
+ bmpi = wx.wxBitmap(psvtxt_xpm32)
+ iconi:CopyFromBitmap(bmpi)
+ icontxt:AddIcon(iconi)
+ bmpi = wx.wxBitmap(psvtxt_xpm16)
+ iconi:CopyFromBitmap(bmpi)
+ icontxt:AddIcon(iconi)
+
+ return iconimg,icontxt
+end
+
+
+function PrepareKeyNames()
+
+ -- wxMOD-s should be defined in wxLua
+ wx.wxMOD_NONE=0
+ wx.wxMOD_ALT=1 wx.wxMOD_CONTROL=2
+ wx.wxMOD_SHIFT=4 wx.wxMOD_META=8
+
+ wx.wxMOD_MORE_THAN_SHIFT=wx.wxMOD_ALT+wx.wxMOD_META+wx.wxMOD_CONTROL
+
+ mod_text={
+ [wx.wxMOD_NONE]="NORM",
+ [wx.wxMOD_SHIFT]="SHIFT",
+ [wx.wxMOD_CONTROL]="CTRL",
+ [wx.wxMOD_CONTROL+wx.wxMOD_SHIFT]="SHIFTCTRL",
+ [wx.wxMOD_ALT]="ALT",
+ [wx.wxMOD_ALT+wx.wxMOD_SHIFT]="SHIFTALT",
+ [wx.wxMOD_ALT+wx.wxMOD_CONTROL]="CTRLALT",
+ [wx.wxMOD_ALT+wx.wxMOD_CONTROL+wx.wxMOD_SHIFT]="SHIFTCTRLALT",
+ --
+ [wx.wxMOD_META]="META",
+ [wx.wxMOD_SHIFT+wx.wxMOD_META]="SHIFTMETA",
+ [wx.wxMOD_CONTROL+wx.wxMOD_META]="CTRLMETA",
+ [wx.wxMOD_CONTROL+wx.wxMOD_SHIFT+wx.wxMOD_META]="SHIFTCTRLMETA",
+ [wx.wxMOD_ALT+wx.wxMOD_META]="ALTMETA",
+ [wx.wxMOD_ALT+wx.wxMOD_SHIFT+wx.wxMOD_META]="SHIFTALTMETA",
+ [wx.wxMOD_ALT+wx.wxMOD_CONTROL+wx.wxMOD_META]="CTRLALTMETA",
+ [wx.wxMOD_ALT+wx.wxMOD_CONTROL+wx.wxMOD_SHIFT+wx.wxMOD_META]="SHIFTCTRLALTMETA",
+ }
+
+ key_text={
+ [wx.WXK_INSERT]="INS",
+ [wx.WXK_DELETE]="DEL",
+ [wx.WXK_HOME]="HOME",
+ [wx.WXK_END]="END",
+ [wx.WXK_PAGEUP]="PAGE_UP",
+ [wx.WXK_PAGEDOWN]="PAGE_DOWN",
+ [wx.WXK_UP]="UP_ARR",
+ [wx.WXK_DOWN]="DOWN_ARR",
+ [wx.WXK_LEFT]="LEFT_ARR",
+ [wx.WXK_RIGHT]="RIGHT_ARR",
+ [wx.WXK_TAB]="TAB",
+ [wx.WXK_ESCAPE]="ESC",
+ --
+ [wx.WXK_NUMPAD_INSERT]="INS",
+ [wx.WXK_NUMPAD_DELETE]="DEL",
+ [wx.WXK_NUMPAD_HOME]="HOME",
+ [wx.WXK_NUMPAD_END]="END",
+ [wx.WXK_NUMPAD_PAGEUP]="PAGE_UP",
+ [wx.WXK_NUMPAD_PAGEDOWN]="PAGE_DOWN",
+ [wx.WXK_NUMPAD_UP]="UP_ARR",
+ [wx.WXK_NUMPAD_DOWN]="DOWN_ARR",
+ [wx.WXK_NUMPAD_LEFT]="LEFT_ARR",
+ [wx.WXK_NUMPAD_RIGHT]="RIGHT_ARR",
+ [wx.WXK_NUMPAD_DIVIDE]="DIVIDE",
+ [wx.WXK_NUMPAD_MULTIPLY]="MULTIPLY",
+ [wx.WXK_NUMPAD_SUBTRACT]="SUBSTRACT",
+ [wx.WXK_NUMPAD_ADD]="ADD",
+ [wx.WXK_NUMPAD_ENTER]="RETURN",
+ [wx.WXK_NUMPAD_EQUAL]="EQUAL",
+ [wx.WXK_NUMPAD_BEGIN]="BEGIN",
+ --[wx.WXK_NUMPAD_DECIMAL]="",
+ --[wx.WXK_NUMPAD_SEPARATOR]="",
+ }
+ for i = 1, 24 do s=string.format("F%d",i) key_text[wx["WXK_" .. s]]=s end
+ for i = 0, 9 do s=string.format("%d",i) key_text[wx["WXK_NUMPAD" .. s]]=s end
+
+ char_text={
+ [wx.WXK_RETURN]="RETURN",
+ [wx.WXK_BACK]="BACK",
+ [string.byte("`")]="GRAVE",
+ [string.byte("-")]="MINUS",
+ [string.byte("=")]="EQUAL",
+ [string.byte("\\")]="BACKSLASH",
+ [string.byte("[")]="BRACKETL",
+ [string.byte("]")]="BRACKETR",
+ [string.byte(";")]="SEMICOLON",
+ [string.byte("'")]="ACUTE",
+ [string.byte(",")]="COMMA",
+ [string.byte(".")]="PERIOD",
+ [string.byte("/")]="SLASH",
+ }
+ for i = string.byte("0"), string.byte("9") do
+ char_text[i]=string.format("%c",i) end
+ for i = string.byte("A"), string.byte("Z") do
+ char_text[i]=string.format("%c",i) end
+
+ char_shift_text={
+ [string.byte(">")]="GREATER",
+ [string.byte("<")]="LESS",
+ }
+end
+
+function MakeQueue()
+ return { b=0; t=0;
+ add = function(s,str) s.t=s.t+1 s[s.t]=str end;
+ insert = function(s,str)
+ for i=1,s.t do s[i+1]=s[i] end
+ s[1]=str s.t=s.t+1
+ end;
+ get = function(s)
+ s.b=s.b+1 local str=s[s.b]
+ if s.b>=s.t then s.b=0 s.t=0 end
+ return str
+ end;
+ getMax = function(s)
+ s.b=s.b+1 local str=s[s.b]
+ while s.b<s.t and str:len()<30000 do
+ s.b=s.b+1 str=str.."\n"..s[s.b]
+ end
+ if s.b>=s.t then s.b=0 s.t=0 end
+ return str
+ end;
+ peek = function(s) return s[s.b+1] end;
+ isEmpty = function(s) return s.t==0 end;
+ }
+end
+
+function MakeIdList()
+ return {
+ newId = function(s,str)
+ local id="ID_"..str
+ s[id]=wx.wxNewId()
+--or if not s[id] then s[id]=wx.wxNewId() end
+ s["NAM_"..s[id]]=str
+ return s[id]
+ end;
+ newObj = function(s,str,creator)
+ local id="OBJ_"..str
+ s[id]=creator
+--or if not s[id] then s[id]=creator end
+ return s[id]
+ end;
+ newCtrl = function(s,id,type)
+ table.insert(s,{id=id,type=type})
+ end;
+ getId = function(s,str) return s["ID_"..str] end;
+ getObj = function(s,str) return s["OBJ_"..str] end;
+ getName = function(s,id) return s["NAM_"..id] end;
+ }
+end
+
+local iconimg, icontxt = MakeIcons()
+gsobj.menu = MakeIdList()
+local RunPScode, RunDSCcode = MakeQueue(), MakeQueue()
+local StdInCode = MakeQueue()
+
+local Mouse = { Cnone=0, Czoom=1, Cpane=2, Cmeasure=3, Cscroll=4,
+ Cendmeas=5, Cdblclick=6;
+ cursorHand=wx.wxCursor(wx.wxCURSOR_HAND),
+ cursorMag=wx.wxCursor(wx.wxCURSOR_MAGNIFIER),
+ cursorCross=wx.wxCursor(wx.wxCURSOR_BLANK); -- wxCURSOR_CROSS, wx.wxCURSOR_BULLSEYE
+ penRed=wx.wxPen("RED",1,wx.wxSOLID), penBlue=wx.wxPen("BLUE",1,wx.wxSOLID);
+ bx=0, by=0, ex=0, ey=0, scroln=0, CMD=0, mod=0, timer=0,}
+
+local Dobject = { n=0, id={},
+Oline=1, Orect=2, Ocros=3, }
+Dobject.pens={ [-1] = wx.wxTRANSPARENT_PEN, [0] =
+wx.wxBLACK_PEN, wx.wxPen("BLUE",1,wx.wxSOLID),
+wx.wxGREEN_PEN, wx.wxCYAN_PEN,
+wx.wxRED_PEN, wx.wxPen("MAGENTA",1,wx.wxSOLID),
+wx.wxPen("YELLOW",1,wx.wxSOLID), wx.wxWHITE_PEN,
+wx.wxPen("BLACK",3,wx.wxSOLID), wx.wxPen("BLUE",3,wx.wxSOLID),
+wx.wxPen("GREEN",3,wx.wxSOLID), wx.wxPen("CYAN",3,wx.wxSOLID),
+wx.wxPen("RED",3,wx.wxSOLID), wx.wxPen("MAGENTA",3,wx.wxSOLID),
+wx.wxPen("YELLOW",3,wx.wxSOLID), wx.wxPen("WHITE",3,wx.wxSOLID),
+}
+Dobject.brushess={ [-1] = wx.wxTRANSPARENT_BRUSH, [0] =
+wxBLACK_BRUSH, wx.wxBLUE_BRUSH,
+wxGREEN_BRUSH, wxCYAN_BRUSH,
+wxRED_BRUSH, wx.wxBrush("MAGENTA",wx.wxSOLID),
+wx.wxBrush("YELLOW",wx.wxSOLID), wxWHITE_BRUSH,
+wxGREY_BRUSH
+}
+
+
+local v_quiet,v_normal,v_verbose=2,6,10
+local verbose=v_normal
+
+function print_debug(...)
+ if verbose>v_normal then print(...) end
+end
+
+function print_message(...)
+ if verbose>v_quiet then print(...) end
+end
+
+function SendEventCommand (c,s,...)
+ RunPScode:add(string.format(s,...) .. " /" .. c .. " EVENTCOMMAND")
+end
+
+function SendDSCEventCommand (c,s,...)
+ RunDSCcode:add(string.format(s,...) .. " /" .. c .. " EVENTCOMMAND")
+end
+
+function SendMenuCommand (m,s)
+ RunInputString()
+ RunPScode:add("/" .. m .. " /" .. s .. " MENUCOMMAND")
+end
+
+function SendKeyCommand (k,s)
+ RunInputString()
+ RunPScode:add("/" .. k .. " /" .. s .. " KEYCOMMAND")
+end
+
+function SendMouseCommand (xa,ya,xb,yb,c,s)
+ RunPScode:add(string.format("%d %d %d %d /%s /%s MOUSECOMMAND",xa,ya,xb,yb,c,s))
+end
+
+function SendMouseCommandWithStatus(mouse,cmd)
+ SendMouseCommand (mouse.bx,mouse.by,mouse.ex,mouse.ey,cmd,mod_text[mouse.mod])
+end
+
+function CallPSVhook (str)
+ local b=str:find(": ")
+ local c,l=str:sub(1,b-1),str:sub(b+2,-1)
+ local f,s=l:sub(1,1),l:sub(2,2)
+ local p={} for w in l:gmatch("{([^}]*)}") do table.insert(p,w) end
+ print_debug(_T("PSVhook>>") .. str .."\n")
+ if c=="FINDDSC" then
+ StartDSCthread(p[1])
+ elseif c=="DIALOG" then
+ MakeFileDialogBox(f,p[1],p[2],p[3],p[4])
+ elseif c=="DLGBOX" then
+ MakeDialogBox(f,p[1],p[2],p[3],p[4])
+ elseif c=="MESSAGEBOX" then
+ MakeMessageBox(f,p[1])
+ elseif c=="MENU" then
+ MakeMenu(f,s,p[1],p[2],p[3])
+ elseif c=="STATUS" then
+ MakeStatusLine(f,s,p[1],p[2])
+ elseif c=="REFRESH" then
+ MakeRefreshEvent(p[1])
+ elseif c=="DRAW" then
+ DrawObjectEvent(f,s,p[1],p[2],p[3])
+ elseif c=="HOOK" then
+ -- reserved entry for debugging
+ elseif c=="CONFIG" then
+ MakeConfigFile(f,p[1],p[2],p[3])
+ elseif c=="CONSOLE" then
+ MakeConsole(f,p[1])
+ elseif c=="INFO" then
+ SendInfoEvent()
+ elseif c=="LOCALE" then
+ SendLocaleEvent(f,p[1])
+ elseif c=="LUA" then
+ RunLuaCode(f,p[1])
+ else
+ error(_T("Unrecognized !PSV callback: ") .. str)
+ end
+end
+
+function MakeRefreshEvent(fname)
+ SetPSFile(PSFName(fname))
+end
+
+function MakeConfigFile(l,a,b,c)
+ if gsobj.config then
+ gsobj.config:SetPath("/" .. a)
+ if l=="S" then
+ gsobj.config:Write(b,c)
+ elseif l=="G" then
+ local _,r=gsobj.config:Read(b,c)
+ if not _ then r=c end
+ local n=tonumber(r) if not n then n=0 end
+ SendEventCommand ("CONFIG","(%s) %d /%s",r,n,a.."_"..b)
+ end
+ end
+end
+
+function MakeConsole(l,a)
+ if not console then
+ -- it is now not used -- console can be hidden but always is defined
+ if l=="S" then
+ local wtitle=PS_VIEW_NAME .. _T(" Console")
+ if gsargs.psf_name~="" then wtitle=gsargs.psf_name .. " -- " .. wtitle end
+ console = wx.wxFrame( wx.NULL, wx.wxID_ANY, wtitle,
+ wx.wxDefaultPosition, wx.wxDefaultSize, wx.wxDEFAULT_FRAME_STYLE)
+ gswin.logwindow = wx.wxTextCtrl(console, wx.wxID_ANY, "",
+ wx.wxDefaultPosition, wx.wxDefaultSize,
+ wx.wxTE_MULTILINE + wx.wxTE_READONLY + wx.wxTE_RICH)
+ console:Connect(wx.wxEVT_CLOSE_WINDOW, function (event) console:Hide() end)
+ InitializeConsole()
+ ConfigRestoreFramePosition(console, "ConsoleWindow")
+ console:SetIcons(icontxt)
+ function print(...)
+ local str=""
+ for i,v in ipairs{...} do str=str..tostring(v) end
+ gswin.logwindow:AppendText(str)
+ end
+ console:Show()
+ end
+ elseif l=="S" then
+ console:Show()
+ console:Iconize(false)
+ elseif l=="H" then
+ console:Hide()
+ elseif l=="P" then
+ gswin.logwindow:AppendText(a)
+ elseif l=="A" then
+ gswin.editwindow:WriteText(a)
+ end
+end
+
+function SendInfoEvent()
+ local info,infodict="","<<"
+ infodict=infodict.."/ProgramName (" .. PS_VIEW_NAME ..") "
+ info=info.. _T("This is ") .. PS_VIEW_NAME ..", "
+ infodict=infodict.."/ProgramVersion " .. PS_VIEW_VERSION .." "
+ info=info.. _T("version ") .. PS_VIEW_VERSION .."\n"
+ infodict=infodict.."/wxLuaName (" .. wxlua.wxLUA_VERSION_STRING ..") "
+ info=info.. _T("built with ") .. wxlua.wxLUA_VERSION_STRING .." "
+ infodict=infodict.."/LuaName (" .. _VERSION ..") "
+ info=info.."(" .. _VERSION ..") "
+ infodict=infodict.."/wxWidgetsName (" .. wx.wxVERSION_STRING ..") "
+ info=info.. _T("and ") .. wx.wxVERSION_STRING .."\n"
+ if gsobj.gsdll then
+ infodict=infodict.."/GhostscriptVersion " .. gsobj.gsdll:GetVersion() .." "
+ info=info.. _T("linked with Ghostscript ") .. gsobj.gsdll:GetVersion() .."\n" end
+ infodict=infodict.."/OSDescription (" .. wx.wxGetOsDescription() ..") "
+ info=info.. _T("running under ") .. wx.wxGetOsDescription() .."\n"
+--
+ if gsargs.psf_name~="" then
+ infodict=infodict.."/OpenedFile (" .. gsargs.psf_name ..") "
+ info=info.. _T("started on ") .. gsargs.psf_name .." "
+ infodict=infodict.."/OpenedDir (" .. gsargs.psf_dir ..") "
+ info=info.. _T("in ") .. gsargs.psf_dir .."\n"
+ end
+ infodict=infodict.."/GSDLL (" .. gsargs.dllloc ..") "
+ infodict=infodict.."/GSLIB (" .. gsargs.libloc ..") "
+ infodict=infodict.."/GSFONT (" .. gsargs.fontloc ..") "
+ infodict=infodict.."/XGSLIB (" .. gsargs.gslib ..") "
+ infodict=infodict.."/PSVLIB (" .. gsargs.psvlib ..") "
+ infodict=infodict..">>"
+ SendEventCommand ("INFO","(%s) %s 0",info,infodict)
+end
+
+function SendLocaleEvent(f,a)
+ if f=="T" then
+ local l=wx.wxGetTranslation(a)
+ if l~=a then
+ SendEventCommand ("LOCALE","(%s) (%s) 1",a,l)
+ else
+ SendEventCommand ("LOCALE","(%s) (%s) -1",a,a)
+ end
+ elseif f=="I" then
+ SendEventCommand ("LOCALE","(%s) %d 0", gsobj.locale:GetLocale(), gsobj.locale:GetLanguage())
+ elseif f=="S" then
+ local lang=gsobj.locale.FindLanguageInfo(a)
+ SetLocale(lang.Language)
+ end
+end
+
+function RunLuaCode(l,a)
+ if l=="R" then
+ local torun=loadstring(a)
+ if torun then torun() end
+ end
+end
+
+function StartDSCthread(fname)
+ if gsobj.dscthread then return end
+ gsobj.dscthread=coroutine.wrap(ReadDSCcomments)
+ local res=gsobj.dscthread(fname)
+ if res==1 then -- thread created succesfuly
+ elseif res==0 then -- --''-- and finished
+ gsobj.dscthread=function() return 0 end
+ else
+ error(_T("Unexpected error during creating DSC thread."))
+ end
+end
+
+function ReadDSCcomments(fname)
+ local psf_dir, psf_name = PSFName(fname)
+ local ffname = psf_dir..psf_name
+ local psfile,err=io.open(ffname,"rb")
+ if not psfile then
+ SendDSCEventCommand ("ENDDSC","(%s) %d %d",err,0,1)
+ SetPSFile("","")
+ return 0
+ end
+ SetPSFile(psf_dir, psf_name)
+ local pstr=psfile:read(4)
+ local pslen=psfile:seek("end")
+ local psbeg,psend=0,pslen
+ if pstr=="%PDF" then
+ SendDSCEventCommand ("PDFFOUND","(%s) %d %d",ffname,0,pslen)
+ else
+ coroutine.yield(1)
+ if pstr==string.char(0xC5,0xD0,0xD3,0xC6) then
+ psfile:seek("set",4) pstr=psfile:read(8)
+ local b={pstr:byte(1,4)} psbeg=b[1]+(b[2]+(b[3]+b[4]*256)*256)*256
+ b={pstr:byte(5,8)} psend=psbeg+b[1]+(b[2]+(b[3]+b[4]*256)*256)*256
+ if psend>pslen then
+ print_message(_T("Improper preview information -- ignoring\n"))
+ psbeg=0 psend=pslen
+ end
+ end
+ SendDSCEventCommand ("FILEFOUND","(%s) %d %d",ffname,psbeg,psend)
+ local pp=psfile:seek("set",psbeg)
+ pstr=psfile:read("*l")
+ local pn=psfile:seek()
+ if pstr:match("^%%!PS") then
+ SendDSCComment(pstr,pp,pn) -- %!PS Adobe
+ coroutine.yield(1)
+ local pstrec="\n"
+ local psb,pse,pseb,psee,comm
+ while pn<psend do
+ if pstrec=="" and pstr:sub(-1):match("[\n\r%%]") then
+ pstrec=pstr:sub(-3) end
+ pstr=psfile:read(60000)-- -/+ 2^16
+ pp,pn=pn,psfile:seek()
+ if pstrec~="" then
+ pstr=pstrec..pstr pp=pp-pstrec:len() pstrec="" end
+ pse=1
+ while true do
+ psb,pse = pstr:find("%%",pse,true)
+ if psb then
+ if pstr:sub(psb-1,pse):match("[\n\r]%%[%%D!]") then
+ pseb,psee = pstr:find("[\n\r]+",pse)
+ if pseb then
+ pse=psee
+ SendDSCComment(pstr:sub(psb,pseb-1),pp+psb,pp+pse)
+ elseif pn==psend then
+ pse=pstr:len()
+ SendDSCComment(pstr:sub(psb,pse),pp+psb,pp+pse)
+ elseif psb+1024<pn then
+ pse=psb+255
+ SendDSCComment(pstr:sub(psb,pse),pp+psb,pp+pse)
+ else
+ pse=pstr:len() pstrec=pstr:sub(psb-1)
+ end
+ end
+ else break end
+ end
+ coroutine.yield(pn)
+ end
+--[[
+-- for pstr in psfile:lines() do
+-- if pstr:match("^%%[%%!D]") then
+-- SendDSCEventCommand ("DSCCOMMENT","(%s) %d %d",pstr,pp,pn)
+-- coroutine.yield(pp)
+-- end
+-- end
+--]]
+ end
+ end
+ SendDSCEventCommand ("ENDDSC","(%s) %d %d",ffname,0,0)
+ psfile:close()
+ return 0
+end
+
+function SendDSCComment(comm,begc,endc)
+-- comm=comm:gsub("[\128-\255]","#")
+ comm=comm:gsub("([\\%(%)])","\\%1")
+ SendDSCEventCommand ("DSCCOMMENT","(%s) %d %d",comm,begc,endc)
+end
+
+function MakeStatusLine(l,m,a,b)
+ if not gswin.statusBar then
+ if l=="C" then gswin.statusBar=frame:CreateStatusBar() end
+ elseif l=="D" then
+ gswin.statusBar:Show(m~="F")
+ elseif l=="P" then
+ gsobj.SBsty,gsobj.SBall={},{} local wid={}
+ for wi,al,ap in a:gmatch("([0-9]+)([lcr]?)([tbn]?)") do
+ wi=tonumber(wi) if wi==0 then wi=-1 end table.insert(wid,wi)
+ if al=="l" then al=2 elseif al=="r" then al=1 else al=3 end
+ table.insert(gsobj.SBall,al)
+ if ap=="t" then ap=wx.wxSB_RAISED elseif ap=="b" then ap=wx.wxSB_NORMAL
+ else ap=wx.wxSB_FLAT end table.insert(gsobj.SBsty,ap)
+ end
+ gswin.statusBar:SetFieldsCount(#wid)
+ gswin.statusBar:SetStatusWidths(wid)
+ gswin.statusBar:SetStatusStyles(gsobj.SBsty)
+ elseif l=="T" then
+ local i,al,ap=a:match("([0-9]+)([lcr]?)([tbn]?)")
+ i=tonumber(i)
+ if al=="l" then al=2 elseif al=="r" then al=1 elseif al=="c" then al=3 end
+ if ap=="t" then ap=wx.wxSB_RAISED elseif ap=="n" then ap=wx.wxSB_FLAT
+ elseif ap=="b" then ap=wx.wxSB_NORMAL end
+ if not b then b="" end
+ gswin.statusBar:SetStatusText(_T(b),i-1)
+ if ap~="" then gsobj.SBsty[i]=ap end
+ gswin.statusBar:SetStatusStyles(gsobj.SBsty)
+ elseif l=="M" then
+ local i=0
+ for t in a:gmatch("([^|]+)|") do
+ if t~="" then gswin.statusBar:SetStatusText(_T(t),i) end i=i+1
+ end
+ end
+end
+
+function MakeMessageBox(kind, text)
+ local style=wx.wxOK+wx.wxICON_INFORMATION
+ if kind=="2" then style=style+wx.wxCANCEL end
+ if kind=="3" then style=wx.wxYES_NO+wx.wxCANCEL+wx.wxICON_QUESTION end
+ if kind=="4" then style=wx.wxYES_NO+wx.wxICON_QUESTION end
+ -- local dialog=wx.wxMessageDialog(frame, title, PS_VIEW_NAME, style)
+ -- local res=dialog:ShowModal()
+ local res=wx.wxMessageBox(_T(text), PS_VIEW_NAME, style, frame)
+ local restr="() 0 /UNKNOWN"
+ if res==wx.wxOK then restr="() 1 /OK" end
+ if res==wx.wxYES then restr="() 1 /YES" end
+ if res==wx.wxNO then restr="() 2 /NO" end
+ if res==wx.wxCANCEL then restr="() 3 /CANCEL" end
+ SendEventCommand("MESSAGEBOX",restr)
+end
+
+function MakeFileDialogBox(kind, filter,file,ext,title)
+ filter:gsub("||$","",1)
+ local dialog
+ if kind=="D" then
+ local dir,title=filter,file
+ if dir=="|" then dir=gsargs.psf_dir
+ elseif dir=="|P" then dir=gsargs.psvlib
+ elseif dir=="|G" then dir=gsargs.gslib end
+ dialog=wx.wxDirDialog(frame, _T(title), dir)
+ else
+ local dir,style=gsargs.psf_dir,wx.wxFD_OPEN+wx.wxFD_FILE_MUST_EXIST
+ if kind=="O" then
+ if file=="|" then file=gsargs.psf_name end
+ elseif kind=="S" then
+ style=wx.wxFD_SAVE+wx.wxFD_OVERWRITE_PROMPT
+ elseif kind=="L" then
+ if file=="|" then file=gsargs.dllloc end
+ local fname=wx.wxFileName(file)
+ dir=fname:GetPath(wx.wxPATH_GET_VOLUME)
+ file=fname:GetFullName()
+ end
+ dialog=wx.wxFileDialog(frame, _T(title), dir, file, _T(filter), style)
+ end
+--
+ local res=dialog:ShowModal()
+ if res==wx.wxID_OK then
+ local resfull=dialog:GetPath()
+ local resdir, resfn, fnoff = PSFName(resfull)
+ resfull:gsub("\\","\\\\") resfull:gsub("%(","\\(") resfull:gsub("%)","\\)")
+ if kind=="L" then
+ SendEventCommand("LIBDIALOG", "(%s) (%s) 0", resdir..resfn, resfull)
+ elseif kind=="D" then
+ SendEventCommand("DIRDIALOG", "(%s) (%s) 0", resdir, resfull)
+ elseif kind=="O" then
+ local wild=dialog:GetFilterIndex()
+ SendEventCommand("OPENDIALOG", "(%s) %d %d", resdir..resfn, fnoff, wild)
+ elseif kind=="S" then
+ SendEventCommand("SAVEDIALOG", "(%s) %d 0", resdir..resfn, fnoff)
+ end
+ end
+ dialog:Destroy()
+end
+
+function MakeDialogBox(l, a,b,c,d)
+ local function topixels(v) return math.ceil(2.5*tonumber(v)) end
+ local dialog, objlst = gswin.dialog, gsobj.dialog
+ local pos=wx.wxDefaultPosition
+ local size=wx.wxDefaultSize
+ local id,title="","Untitled"
+ local type,state=a:sub(1,1),a:sub(2)
+ if c then
+ local x,y,w,h=c:match("([0-9]+),([0-9]+),([0-9]+),([0-9]+)")
+ if x then
+ pos=wx.wxPoint(topixels(x),topixels(y))
+ size=wx.wxSize(topixels(w),topixels(h))
+ end
+ if b then id=b end
+ if d then title=d end
+ else
+ local w,h=a:match("([0-9]+),([0-9]+)")
+ if w then
+ if wx.__WXMSW__ then h=h+10 end -- titlebar correction
+ size=wx.wxSize(topixels(w),topixels(h))
+ end
+ if b then title=b end
+ end
+--
+ if l=="I" then -- dialog box init
+ gswin.dialog=wx.wxDialog(frame,wx.wxID_ANY,_T(title),pos,size)
+ gsobj.dialog=MakeIdList()
+ return
+ else
+ if dialog==nil then error("Operation on uninitialized DLGBOX.") end
+ end
+ if l=="B" then -- add push button
+ if type=="O" then
+ objlst:newObj(id,wx.wxButton(dialog,wx.wxID_OK,_T(title),pos,size))
+ elseif type=="C" then
+ objlst:newObj(id,wx.wxButton(dialog,wx.wxID_CANCEL,_T(title),pos,size))
+ elseif type=="P" then
+ local obj=objlst:newObj(id,wx.wxButton(dialog,wx.wxID_ANY,_T(title),pos,size))
+ obj:Connect(wx.wxEVT_COMMAND_BUTTON_CLICKED, function (event)
+ SendEventCommand("DIALOG", "() /%s /CLICKED",id) end )
+ elseif type=="G" then
+ objlst:newObj(id,wx.wxStaticBox(dialog,wx.wxID_ANY,_T(title),pos,size))
+ end
+ elseif l=="K" then -- add check button
+ local obj
+ if type=="K" then
+ obj=objlst:newObj(id,wx.wxCheckBox(dialog,wx.wxID_ANY,_T(title),pos,size,wx.wxCHK_2STATE))
+ elseif type=="3" then
+ obj=objlst:newObj(id,wx.wxCheckBox(dialog,wx.wxID_ANY,_T(title),pos,size,wx.wxCHK_3STATE))
+ elseif type=="S" then
+ obj=objlst:newObj(id,wx.wxRadioButton(dialog,wx.wxID_ANY,_T(title),pos,size,wx.wxRB_GROUP))
+ elseif type=="R" then
+ obj=objlst:newObj(id,wx.wxRadioButton(dialog,wx.wxID_ANY,_T(title),pos,size,0))
+ end
+ if type=="3" then objlst:newCtrl(id,"CHECK3") else objlst:newCtrl(id,"CHECK") end
+ if state=="C" or state=="+" then obj:SetValue(true)
+ elseif state=="U" or state=="-" then obj:SetValue(false)
+ elseif state=="N" or state=="0" then
+ obj:Set3StateValue(wx.wxCHK_UNDETERMINED)
+ end
+ elseif l=="E" then -- add edit box
+ local style,valid=wx.wxTE_LEFT,wx.wxDefaultValidator
+ if type=="N" then
+ elseif type=="P" then style=style+wx.wxTE_PASSWORD
+ elseif type=="M" then style=style+wx.wxTE_MULTILINE
+ elseif type=="D" then valid=wx.wxTextValidator(wx.wxFILTER_NUMERIC)
+ end
+ objlst:newObj(id,wx.wxTextCtrl(dialog,wx.wxID_ANY,_T(state),pos,size,style,valid))
+ objlst:newCtrl(id,"EDIT")
+ elseif l=="T" then -- add static (text)
+ local style,text,border=wx.wxALIGN_CENTER,true,false
+ if type=="C" then
+ elseif type=="L" then style=wx.wxALIGN_LEFT
+ elseif type=="R" then style=wx.wxALIGN_RIGHT
+ elseif type=="D" then border=true
+ elseif type=="U" then border=true
+ elseif type=="W" then border=true text=false
+ elseif type=="B" then border=true text=false
+ end
+ if border then
+ objlst:newObj(id.."F",wx.wxStaticBox(dialog,wx.wxID_ANY,"",pos,size))
+ end
+ if text then
+ local obj = objlst:newObj(id,
+ wx.wxStaticText(dialog,wx.wxID_ANY,_T(title),pos,wx.wxDefaultSize,style))
+ local nsize=obj:GetSize()
+ pos=wx.wxPoint(pos.x+2,pos.y+(size:GetHeight()-nsize:GetHeight())/2+4)
+ size:DecBy(4,4) obj:Move(pos) obj:SetSize(size)
+ end
+ elseif l=="L" then -- add list box
+ local style,list,ini=wx.wxLB_SINGLE,{},nil
+ if type=="M" then style=wx.wxLB_MULTIPLE end
+ for v in state:gmatch("([^|]*)|") do if ini then table.insert(list,_T(v)) else ini=v end end
+ local obj=objlst:newObj(id,wx.wxListBox(dialog,wx.wxID_ANY,pos,size,list,style))
+ objlst:newCtrl(id,"LIST")
+ if ini~="" then obj:SetSelection(tonumber(ini)) end
+ elseif l=="C" then -- add combo (edit+list) box
+ local style,list,ini=wx.wxCB_DROPDOWN,{},nil
+ if type=="L" then style=wx.wxCB_SIMPLE end
+ for v in state:gmatch("([^|]*)|") do if ini then table.insert(list,_T(v)) else ini=v end end
+ local obj=objlst:newObj(id,wx.wxComboBox(dialog,wx.wxID_ANY,_T(title),pos,size,list,style))
+ objlst:newCtrl(id,"COMBO")
+ if ini~="" then obj:SetSelection(tonumber(ini)) end
+ elseif l=="S" then -- dialog box start (show and process)
+ ShowDialogBox()
+ gswin.dialog:Destroy()
+ gswin.dialog=nil gsobj.dialog=nil
+ end
+end
+
+function ShowDialogBox()
+ local result=gswin.dialog:ShowModal()
+ if result==wx.wxID_OK then result="OK"
+ for i,v in ipairs(gsobj.dialog) do
+ local type, obj, res = v.type, gsobj.dialog:getObj(v.id), ""
+ if type=="CHECK" then
+ type="UNCHECKED"
+ if obj:GetValue() then type="CHECKED" end
+ elseif type=="CHECK3" then
+ type="UNCHECKED"
+ if obj:Get3StateValue()==wx.wxCHK_UNDETERMINED then type="INDETERMINATE"
+ elseif obj:Get3StateValue()==wx.wxCHK_CHECKED then type="CHECKED" end
+ elseif type=="EDIT" then
+ res=obj:GetValue()
+ elseif type=="LIST" then
+ for i=0,obj:GetCount()-1 do
+ if obj:IsSelected(i) then res=res.."1" else res=res.."0" end
+ end
+ elseif type=="COMBO" then
+ res=obj:GetValue()
+ else
+ error(_T("Unknown type of control in ShowDialog -- can't happen."))
+ end
+ SendEventCommand("DIALOG", "(%s) /%s /%s", res, v.id, type)
+ end
+ elseif result==wx.wxID_CANCEL then result="CANCEL"
+ else result="UNDEFINED" end
+ SendEventCommand("DIALOG", "() /%s /ENDDIALOG", result)
+end
+
+function MakeMenu(l,m,a,b,c)
+ local objlst=gsobj.menu
+ if not gswin.menuBar then
+ gswin.menuBar=wx.wxMenuBar()
+ objlst:newObj("MAIN",gswin.menuBar)
+ frame:SetMenuBar(gswin.menuBar)
+ end
+ if l=="I" then
+ local pare=objlst:getObj(a)
+ if not pare then return false end
+ if m=="C" then -- extra option required by wxWidgets
+ pare:AppendCheckItem(objlst:newId(b),_T(c))
+ else
+ pare:Append(objlst:newId(b),_T(c))
+ end
+ elseif l=="S" then
+ local pare=objlst:getObj(a)
+ local menu=objlst:newObj(b,wx.wxMenu())
+ if not pare or not menu then return false end
+ if a=="MAIN" then
+ pare:Append(menu,_T(c))
+ else
+ pare:Append(objlst:newId(b),_T(c),menu)
+ end
+ elseif l=="H" then
+ local pare=objlst:getObj(a)
+ if pare then pare:AppendSeparator() else return false end
+ elseif l=="C" then
+ local item=gswin.menuBar:FindItem(objlst:getId(a))
+ if item then item:SetText(_T(b)) else return false end
+ elseif l=="U" then
+ local item=gswin.menuBar:FindItem(objlst:getId(a))
+ if not item then return false end
+ item:Enable(m=="N" or m=="C")
+ item:Check(m=="C" or m=="B")
+ elseif l=="D" then
+ gswin.menuBar:Show(m~="F")
+ if m=="R" then gswin.menuBar:Refresh() end
+ end
+end
+
+function DrawObjectEvent(f,s,id,dim,pen)
+ if f=="O" then
+ if s=="C" then CreateOverlay()
+ elseif s=="D" then DestroyOverlay()
+ elseif s=="T" then ToggleOverlay() end
+ elseif f=="D" then
+ if s=="A" then AddDrawObject(id,dim,pen)
+ elseif s=="M" then MoveDrawObject(id,dim,pen)
+ elseif s=="D" then DeleteDrawObject(id)
+ elseif s=="M" then ClearDrawObjects() end
+ end
+end
+
+function CreateOverlay()
+ local w, h = gsobj.image.w, gsobj.image.h
+ if not gsobj.bbmp then gsobj.bbmp=wx.wxBitmap(w,h) end
+ if not gsobj.obmp then gsobj.obmp=wx.wxBitmap(w,h) end
+ local bdc=wx.wxMemoryDC()
+ bdc:SelectObject(gsobj.bbmp)
+ gsobj.image:CopyOnto(bdc,0,0,w,h,0,0)
+ bdc:delete()
+ if Dobject.n==0 then
+ gswin.gswindow:Connect(wx.wxEVT_PAINT, OnPaintExtra)
+ end
+ gsstat.inoverlay=true
+ gsstat.drawoverlay=true
+end
+
+function ToggleOverlay()
+ gsstat.drawoverlay = not gsstat.drawoverlay
+end
+
+function DestroyOverlay()
+ if gsstat.inoverlay then
+ gsstat.inoverlay=false
+ if gsstat.drawoverlay then
+ gsobj.image=gsobj.overlay
+ gswin.gswindow:SetGsImage(gsobj.image)
+ gsstat.drawoverlay=false
+ end
+ gsobj.overlay=nil
+ if gsobj.bbmp then gsobj.obmp:delete() gsobj.obmp=nil end
+ if gsobj.obmp then gsobj.bbmp:delete() gsobj.bbmp=nil end
+ end
+ if Dobject.n==0 then
+ gswin.gswindow:Disconnect(wx.wxEVT_PAINT)
+ end
+end
+
+function OnPaintExtra(event)
+ local dc=wx.wxPaintDC(gswin.gswindow)
+ local xd, yd, w, h, xs, ys = 0, 0, gsobj.image.w, gsobj.image.h, 0, 0
+ local sdc
+ if gsstat.inoverlay then
+ if gsstat.drawoverlay then
+ dc:DrawBitmap(gsobj.bbmp,0,0,false)
+ else
+ -- if gsobj.image.r then
+ sdc=wx.wxMemoryDC() sdc:SelectObject(gsobj.bbmp)
+ gsobj.image:CopyOnto(sdc,xd,yd,w,h,xs,ys)
+ sdc:delete()
+ gsobj.image:CopyOnto(dc,xd,yd,w,h,xs,ys)
+ end
+ if gsobj.overlay then
+ sdc=wx.wxMemoryDC() sdc:SelectObject(gsobj.obmp)
+ if gsstat.drawoverlay and gsobj.overlay.r then
+ gsobj.overlay.r=false
+ gsobj.overlay:CopyOnto(sdc,xd,yd,w,h,xs,ys)
+ sdc:delete()
+ local omask=wx.wxMask(gsobj.obmp,wx.wxWHITE)
+ gsobj.obmp:SetMask(omask)
+ sdc=wx.wxMemoryDC() sdc:SelectObject(gsobj.obmp)
+ end
+ -- dc:Blit(xd,yd,w,h,sdc,xs,ys,wx.wxEQUIV) --EQUIV
+ dc:Blit(xd,yd,w,h,sdc,xs,ys,wx.wxCOPY,true)
+ sdc:delete()
+ end
+ else
+ gsobj.image:CopyOnto(dc,xd,yd,w,h,xs,ys)
+ end
+ if Dobject.n>0 then
+ -- draw objects
+ end
+ dc:delete()
+end
+
+function AddDrawObject(id,dim,pen)
+ if Dobject.n==0 then CreateDrawObjects() end
+ if not Dobject.id[id] then
+ Dobject.n=Dobject.n+1 Dobject.id[id]=Dobject.n
+ Dobject[Dobject.n]={id = id, xb = xb, yb = yb, xe = xe, ye = ye,
+ pe = pe, br = br}
+ else
+ MoveDrawObject(id,dim,pen)
+ end
+end
+
+function MoveDrawObject(id,dim,pen)
+ if Dobject.id[id] then
+ Dobject[Dobject.id[id]]={id = id, xb = xb, yb = yb, xe = xe, ye = ye,
+ pe = pe, br = br}
+ end
+end
+
+function DeleteDrawObject(id)
+ if Dobject.id[id] then
+ local k=Dobject.id[id]
+ Dobject.id[id]=nil
+ Dobject.n=Dobject.n-1
+ for i=k,Dobject.n do
+ Dobject[i]=Dobject[i+1]
+ Dobject.id[Dobject[i].id]=i
+ end
+ Dobject[Dobject.n+1]=nil
+ end
+ if Dobject.n==0 then ClearDrawObjects() end
+end
+
+function CreateDrawObjects()
+ if not gsstat.inoverlay then
+ gswin.gswindow:Connect(wx.wxEVT_PAINT, OnPaintExtra)
+ end
+end
+
+function ClearDrawObjects()
+ if Dobject.n>0 then
+ for i=1,Dobject.n do Dobject[i]=nil end
+ Dobject.n=0 Dobject.id={}
+ if not gsstat.inoverlay then
+ gswin.gswindow:Disconnect(wx.wxEVT_PAINT)
+ end
+ -- gswin.gswindow:Refresh()
+ end
+end
+
+
+function MouseButtonEvent(event)
+ local mod=wx.wxMOD_NONE
+ if event:AltDown() then mod=mod+wx.wxMOD_ALT end
+ if event:ControlDown() then mod=mod+wx.wxMOD_CONTROL end
+ if event:ShiftDown() then mod=mod+wx.wxMOD_SHIFT end
+ Mouse.mod=mod
+ if event:ButtonDown() then
+ Mouse.bx,Mouse.by=event:GetPositionXY()
+ Mouse.ex,Mouse.ey=Mouse.bx,Mouse.by
+ if Mouse.CMD==Mouse.Cnone and event:LeftDown() then
+ if wx.wxGetKeyState(32) then
+ Mouse.CMD=Mouse.Cpane
+ else
+ Mouse.CMD=Mouse.Czoom
+ end
+ elseif Mouse.CMD==Mouse.Cnone and event:RightDown() then
+ if not event:ControlDown() then
+ Mouse.CMD=Mouse.Cmeasure
+ else
+ -- Mouse.CMD=Mouse.Cendmeas
+ SendMouseCommandWithStatus(Mouse,"MEAS")
+ end
+ end
+ if Mouse.CMD~=Mouse.Cnone then
+ local cursor=wx.wxNullCursor
+ if Mouse.CMD==Mouse.Cpane then cursor=Mouse.cursorHand end
+ if Mouse.CMD==Mouse.Czoom then cursor=Mouse.cursorMag end
+ if Mouse.CMD==Mouse.Cmeasure then cursor=Mouse.cursorCross end
+ gswin.gswindow:SetCursor(cursor)
+ gswin.gswindow:CaptureMouse()
+ DrawMouseRules()
+ end
+ elseif event:ButtonDClick() then
+ Mouse.bx,Mouse.by=event:GetPositionXY()
+ Mouse.ex,Mouse.ey=Mouse.bx,Mouse.by
+ if event:LeftDClick() then
+ -- Mouse.CMD=Mouse.Cdblclick
+ SendMouseCommandWithStatus(Mouse,"LDBLCLICK")
+ end
+ elseif event:ButtonUp() then
+ if Mouse.CMD~=Mouse.Cnone then
+ DrawMouseRules()
+ Mouse.ex,Mouse.ey=event:GetPositionXY()
+ gswin.gswindow:ReleaseMouse()
+ gswin.gswindow:SetCursor(wx.wxNullCursor)
+ if Mouse.CMD==Mouse.Czoom then
+ if math.abs(Mouse.ex-Mouse.bx)>1 or math.abs(Mouse.ey-Mouse.by)>1 then
+ SendMouseCommandWithStatus(Mouse,"ZOOM") end
+ elseif Mouse.CMD==Mouse.Cpane then
+ if math.abs(Mouse.ex-Mouse.bx)>1 or math.abs(Mouse.ey-Mouse.by)>1 then
+ SendMouseCommandWithStatus(Mouse,"MOVE") end
+ elseif Mouse.CMD==Mouse.Cmeasure then
+ SendMouseCommandWithStatus(Mouse,"MEAS")
+ end
+ Mouse.CMD=Mouse.Cnone
+ end
+ end
+ event:Skip()
+end
+
+function SendWheelEvent()
+ SendMouseCommand (Mouse.scroln,0,0,0,"SCROLL",mod_text[Mouse.mod])
+ Mouse.CMD=Mouse.Cnone Mouse.scroln=0
+end
+
+function MouseWheelEvent(event)
+ if Mouse.timer~=0 then ResetDelayedDo(Mouse.timer) Mouse.timer=0 end
+ Mouse.CMD=Mouse.Cscroll Mouse.scroln=Mouse.scroln+event:GetWheelRotation()
+ Mouse.bx,Mouse.by=0,0
+ if event:ControlDown() or wx.wxGetKeyState(32) then
+ Mouse.ex,Mouse.ey,Mouse.mod=Mouse.scroln/1200*gsobj.image.w,0,wx.wxMOD_CONTROL
+ else
+ Mouse.ex,Mouse.ey,Mouse.mod=0,Mouse.scroln/1200*gsobj.image.h,wx.wxMOD_NONE
+ end
+ DrawMouseRules()
+ if Mouse.scroln~=0 then
+ Mouse.timer=SetDelayedDo(200,function() SendWheelEvent() Mouse.timer=0 end)
+ end
+ event:Skip()
+end
+
+function MouseMotionEvent(event)
+ if Mouse.CMD~=Mouse.Cnone and Mouse.CMD~=Mouse.Cscroll then
+ DrawMouseRules()
+ Mouse.ex,Mouse.ey=event:GetPositionXY()
+ DrawMouseRules()
+ end
+ event:Skip()
+end
+
+function DrawMouseRules()
+ local dc=wx.wxClientDC(gswin.gswindow)
+ if Mouse.CMD==Mouse.Czoom then
+ dc:SetLogicalFunction(wx.wxEQUIV)
+ dc:SetBrush(wx.wxTRANSPARENT_BRUSH)
+ dc:SetPen(Mouse.penRed)
+ dc:DrawRectangle(Mouse.bx,Mouse.by,Mouse.ex-Mouse.bx,Mouse.ey-Mouse.by)
+ elseif Mouse.CMD==Mouse.Cmeasure then
+ dc:SetLogicalFunction(wx.wxEQUIV)
+ dc:SetPen(Mouse.penBlue)
+ dc:CrossHair(Mouse.ex,Mouse.ey)
+ elseif Mouse.CMD==Mouse.Cpane or Mouse.CMD==Mouse.Cscroll then
+ dc:SetLogicalFunction(wx.wxCOPY)
+ dc:SetBrush(wx.wxLIGHT_GREY_BRUSH)
+ dc:SetPen(wx.wxTRANSPARENT_PEN)
+ local xs, ys, w, h = 0, 0, gsobj.image.w, gsobj.image.h
+ local xd, yd = Mouse.ex-Mouse.bx , Mouse.ey-Mouse.by
+ if xd<0 then
+ xs,xd=-xd,0 dc:DrawRectangle(w-xs,0,xs,h)
+ else
+ w=w-xd dc:DrawRectangle(0,0,xd,h)
+ end
+ if yd<0 then
+ ys,yd=-yd,0 dc:DrawRectangle(0,h-ys,w+xd,ys)
+ else
+ h=h-yd dc:DrawRectangle(0,0,w+xd,yd)
+ end
+ gsobj.image:CopyOnto(dc,xd,yd,w,h,xs,ys)
+ end
+ dc:delete()
+end
+
+do local resize = { timer=0, pw=0, ph = 0}
+
+function SendResizeEvent(w,h)
+ if w~=resize.pw or h~=resize.ph then
+ if w*h>resize.pw*resize.ph*2 or w*h*2<resize.pw*resize.ph then
+ gsstat.refr_int=0 -- update refresh timer to new image size
+ gsstat.refresh=0
+ end
+ SendEventCommand ("RESIZE","() %d %d",w,h)
+ resize.pw=w resize.ph=h
+ end
+end
+
+function ProcessResizeEvent(w,h)
+ if resize.timer~=0 then ResetDelayedDo(resize.timer) resize.timer=0 end
+ if h~=0 and w~=0 then
+ resize.timer=SetDelayedDo(140,function() SendResizeEvent(w,h) resize.timer=0 end)
+ end
+end
+
+end -- resize
+
+function SendKeyEvent(code,modif,down)
+ if not down then return false end
+ print_debug("Key pressed: ", code, modif, "\n")
+ if key_text[code] then
+ SendKeyCommand (key_text[code],mod_text[modif])
+ elseif char_text[code] and bit.band(modif,wx.wxMOD_MORE_THAN_SHIFT)>0 then
+ SendKeyCommand (char_text[code],mod_text[modif])
+ else
+ return false
+ end
+ return true
+end
+
+do local inputstr = ""
+
+function SendCharEvent(event)
+ local code=event:GetKeyCode()
+ if char_shift_text[code] then
+ SendKeyCommand (char_shift_text[code],"SHIFT")
+ return false
+ else
+ return EditInputLine(code)
+ end
+end
+
+function EditInputLine(code)
+ if console then inputstr=gswin.editwindow:GetValue()end
+ if code==wx.WXK_RETURN then
+ if inputstr=="" then RunPScode:add("/RETURN /NORM KEYCOMMAND") end
+ RunInputString()
+ elseif code==wx.WXK_BACK then
+ inputstr=inputstr:sub(1,-2)
+ if console then
+ local pos=gswin.editwindow:GetInsertionPoint()
+ gswin.editwindow:Remove(pos-1, pos)
+ end
+ elseif code > 31 and code < 127 then
+ local char=string.char(code)
+ inputstr=inputstr .. char
+ if console then gswin.editwindow:WriteText(char) end
+ else
+ return false
+ end
+ return true
+end
+
+function RunInputString()
+ if console then inputstr=gswin.editwindow:GetValue()end
+ if inputstr~="" then
+ RunPScode:add("{" .. inputstr .. "} stopped {handleerror} if")
+ end
+ inputstr="" if console then gswin.editwindow:Clear() end
+end
+
+end -- inputstr
+
+function StartCheckUpdate ()
+ if gsstat.update~=0 then return end
+ gsstat.update=SetDelayedDo(300,CheckUpdate)
+end
+function StopCheckUpdate ()
+ if gsstat.update~=0 then ResetDelayedDo(gsstat.update) gsstat.update=0 end
+end
+function CheckUpdate ()
+ gsstat.update=0
+ if gsstat.working then return end
+ if gsobj.instancechecker:IsLockUpdated() then
+ SendEventCommand ("REFRESH","(%s) 1 /THISFILE",gsargs.psf_dir..gsargs.psf_name)
+ else
+ StartCheckUpdate ()
+ end
+end
+
+function InitializeGS ()
+
+ gsobj.gsdll = wxghost.wxGsDll(gsargs.dllloc, gsargs.libloc, gsargs.fontloc)
+
+ if (not gsobj.gsdll:isOK()) then
+ ExitPSV_init() error(_T("Failed to link to Ghostscript library"),1)
+ end
+
+ gsobj.ghostscript = wxghost.wxLuaGhostscript()
+
+ gswin.gswindow = wxghost.wxGsWindowX(frame,wx.wxID_ANY)
+
+ local stdoutstr = ""
+ gsobj.ghostscript.OnStdout = function(self, GsOut)
+ stdoutstr=stdoutstr..GsOut
+ local line,rest=stdoutstr:match("^(.*\n)([^\n]*)$")
+ if line then
+ stdoutstr=rest
+ local _m,_p = line:match("^(!PSV_)(.*)$")
+ if _m then
+ CallPSVhook(_p)
+ else
+ print_message(line)
+ end
+ end
+ if gsstat.ready and wxapp:Pending() then
+ gsobj.ghostscript:Suspend()
+ end
+ end
+
+ gsobj.ghostscript.OnStderr = function(self, GsOut)
+ print(GsOut)
+ if gsstat.ready and wxapp:Pending() then
+ gsobj.ghostscript:Suspend()
+ end
+ end
+
+ gsobj.ghostscript.OnStdin = function(self)
+ print_debug("!!!StdIn (PS_View?)\n")
+ if gsstat.ready then
+ gsobj.ghostscript:Suspend()
+ if not StdInCode:isEmpty() then
+ return StdInCode:get() .. "\n"
+ else
+ return "\n"
+ end
+ else
+ return ""
+ end
+ end
+
+ -- gsobj.ghostscript.OnPoll = function(self)
+ -- print_debug("!!!Poll callback\n")
+ -- return 0
+ -- end
+
+ gsobj.ghostscript.OnDisplayOpen = function(self, Image)
+ print_debug("!Display_Open", Image, "\n")
+ if gsstat.ready and wxapp:Pending() then
+ gsobj.ghostscript:Suspend()
+ end
+ return 0
+ end
+
+ -- gsobj.ghostscript.OnDisplayPreSize = function(self, Image) return 0 end
+ gsobj.ghostscript.OnDisplaySize = function(self, Image)
+ print_debug("!Display_Size (image ready)", Image, "\n")
+ if gsstat.drawoverlay then
+ gsobj.overlay=Image
+ gsobj.overlay.w=Image:GetWidth() gsobj.overlay.h=Image:GetHeight()
+ gsobj.overlay.r=false
+ else
+ gsobj.image=Image
+ gsobj.image.w=Image:GetWidth() gsobj.image.h=Image:GetHeight()
+ gswin.gswindow:SetGsImage(gsobj.image) gsobj.image.r=false
+ end
+ if gsstat.ready and wxapp:Pending() then
+ gsobj.ghostscript:Suspend()
+ end
+ return 0
+ end
+
+ gsobj.ghostscript.OnDisplaySync = function(self, Image)
+ print_debug("!Display_Sync", Image, "\n")
+ if gsstat.drawoverlay and gsobj.overlay.r or gsobj.image.r then
+ gswin.gswindow:Refresh()
+ end
+ if gsstat.drawoverlay then gsobj.overlay.r=true else gsobj.image.r=true end
+ if gsstat.ready and wxapp:Pending() then
+ gsobj.ghostscript:Suspend()
+ end
+ return 0
+ end
+
+ gsobj.ghostscript.OnDisplayPage = function(self, Image, copies, flush)
+ print_debug("!!!Display_Page (PS_View?)\n")
+ if gsstat.ready then
+ gsobj.ghostscript:Suspend()
+ gswin.gswindow:Refresh()
+ gsstat.working=false
+ end
+ return 0
+ end
+
+ local rect,mul=nil,0
+ -- OnDisplayUpdate is called on every graphic object (it is too frequent to update window)
+ gsobj.ghostscript.OnDisplayUpdate = function(self, Image, Rect)
+ if gsstat.ready then
+ -- if rect then rect=rect:Union(Rect) else rect=wx.wxRect(Rect) end
+ if gsstat.refresh==0 then
+ gsstat.refresh=SetTimer(gsstat.refr_int)
+ elseif CheckTimer(gsstat.refresh) then
+ if gsstat.drawoverlay then gsobj.overlay.r=true else gsobj.image.r=true end
+ gswin.gswindow:Refresh()
+ -- gswin.gswindow:Refresh(false,rect)
+ if gsstat.refr_int==0 then
+ local sw=wx.wxStopWatch()
+ -- gswin.gswindow:Refresh()
+ gswin.gswindow:Update()
+ gsstat.refr_int=5*sw:Time()
+ print_debug(_T("Update Interval: ") .. gsstat.refr_int .. " ms\n")
+ end
+ gsstat.refresh=SetTimer(gsstat.refr_int)
+ end
+ if wxapp:Pending() then
+ gsobj.ghostscript:Suspend()
+ end
+ end
+ return 0
+ end
+
+ -- gsobj.ghostscript.OnDisplayPreClose = function(self, Image) return 0 end
+ gsobj.ghostscript.OnDisplayClose = function(self, Image)
+ print_debug("!Display_Close (image delete)", Image, "\n")
+ -- close may be called more than one time, so delay window destroy
+ return 0
+ end
+
+ return true
+end
+
+function StartGS ()
+
+ gsobj.ghostscript:Create(gsobj.gsdll, gsargs.args, wxghost.wxGhostscript.colour) -- greyscale)
+
+ local err=gsobj.ghostscript:GetExitCode()
+ if err==wxghost.e_Info then return false end
+ if err==wxghost.e_Quit then return false end
+ if (gsobj.ghostscript:isReady()) then
+ gsstat.ready=true
+ else
+ ExitPSV_init() error(_T("Failed to start Ghostscript"),1)
+ end
+
+ RunPScode:insert("start")
+
+ return true
+end
+
+function PushRunGS ()
+ local torun, isdsc = RunPScode, gsobj.dscthread
+ if isdsc then
+ if not wx.wxIsBusy() then wx.wxBeginBusyCursor() end
+ torun=RunDSCcode
+ if gsobj.dscthread()==0 then
+ if torun:isEmpty() then gsobj.dscthread=nil
+ else gsobj.dscthread=function() return 0 end end
+ end
+ end
+ if gsstat.working then
+ if gsobj.ghostscript:isSuspended() then
+ gsobj.ghostscript:Resume()
+ return true
+ elseif gsobj.ghostscript:isReady() then
+ if not isdsc then
+ if gsstat.drawoverlay then gsobj.overlay.r=true else gsobj.image.r=true end
+ gswin.gswindow:Refresh()
+ end
+ gsstat.working=false
+ end
+ end
+ if not gsstat.working then
+ if torun:isEmpty() then
+ if isdsc then return true -- read more DSC
+ else
+ if wx.wxIsBusy() then wx.wxEndBusyCursor() end
+ StartCheckUpdate()
+ return false -- nothing to do
+ end
+ elseif gsobj.ghostscript:isReady() then
+ if not wx.wxIsBusy() then wx.wxBeginBusyCursor() end
+ StopCheckUpdate()
+ gsstat.working=true gsstat.refresh=0
+ local code=torun:getMax()
+ print_debug(_T("RunPS>>") .. code .."\n")
+ gsobj.ghostscript:RunString(code)
+ return true
+ end
+ end
+ return not IsGSerror()
+end
+
+function ClosePSV ()
+-- print_debug(wxlua.GetGCUserdataInfo(true))
+-- print_debug(wxlua.GetTrackedObjectInfo(true)) -- !!
+ if gsstat.ready then
+ if gsstat.update~=0 then ResetDelayedDo(gsstat.update) end
+ gsobj.gstimer:Stop()
+ gsstat.ready=false
+ print_debug(_T("Close, quit\n"))
+ gsobj.ghostscript:Terminate(wxghost.e_Quit)
+ end
+ if trans then trans:close() end -- for locale text extraction
+ if wx.wxIsBusy() then wx.wxEndBusyCursor() end
+ if gswin.gswindow then gswin.gswindow:Destroy() gswin.gswindow=nil end
+ if gsobj.instancechecker then gsobj.instancechecker:Destroy() end
+ -- ConfigSavePaths(gsargs)
+ ConfigSaveFramePosition(frame, "MainWindow")
+ if console then
+ ConfigSaveFramePosition(console, "ConsoleWindow")
+ console:Destroy()
+ console=nil
+ end
+ gsobj.config:Flush()
+ frame:Destroy()
+end
+
+function IsGSerror()
+ if gsobj.ghostscript:isSuspended() or gsobj.ghostscript:isReady() then
+ return false
+ end
+ ExitPSV(gsobj.ghostscript:GetExitCode())
+ return true
+end
+
+function ExitPSV (err_code)
+ if err_code==0 then frame:Close() return end
+ if gsstat.ready then
+ if gsstat.update~=0 then ResetDelayedDo(gsstat.update) end
+ gsobj.gstimer:Stop()
+ gsstat.ready=false
+ gsobj.ghostscript:Terminate(err_code)
+ end
+ if wx.wxIsBusy() then wx.wxEndBusyCursor() end
+ if gsobj.instancechecker then gsobj.instancechecker:Destroy() end
+ if console then
+ console:Show() frame:Hide()
+ console:Connect(wx.wxEVT_CLOSE_WINDOW, function (event)
+ console:Destroy() frame:Destroy() end)
+ else
+ frame:Destroy()
+ end
+end
+
+function ExitPSV_init ()
+ if gsstat.ready then
+ gsstat.ready=false
+ gsobj.ghostscript:Terminate(gsobj.ghostscript:GetExitCode())
+ end
+ if wx.wxIsBusy() then wx.wxEndBusyCursor() end
+ if gsobj.instancechecker then gsobj.instancechecker:Destroy() end
+ if console then wxapp:SetTopWindow(console) end
+ if frame then frame:Destroy() end
+end
+
+do local time, todo = 0, {}
+
+function TimerTick()
+ time=time+1
+ if todo[time] then
+ todo[time]() todo[time]=nil
+ wx.wxWakeUpIdle()
+ end
+end
+function GetCurrTime() return time end
+function SetTimer(delta) return time+math.ceil(delta/20) end
+function CheckTimer(fin) return time>=fin end
+function SetDelayedDo(delta,run)
+ local fin=SetTimer(delta)
+ while todo[fin] do fin=fin+1 end
+ todo[fin]=run
+ return fin
+end
+function ResetDelayedDo(fin) todo[fin]=nil end
+
+end
+
+function ConnectEvents ()
+
+ gsobj.gstimer = wx.wxTimer(frame)
+ frame:Connect(wx.wxEVT_TIMER, TimerTick)
+ gsobj.gstimer:Start(20)
+
+ local in_iddle = false
+ frame:Connect(wx.wxEVT_IDLE, function (event)
+ if in_iddle then return end in_iddle=true
+ if PushRunGS() then event:RequestMore() end
+ in_iddle=false end)
+
+ frame:Connect(wx.wxEVT_CLOSE_WINDOW, function (event)
+ ClosePSV() event:Skip() end)
+
+ frame:Connect(wx.wxEVT_COMMAND_MENU_SELECTED, function (event)
+ SendMenuCommand(gsobj.menu:getName(event:GetId()),"NORM")
+ end )
+
+ -- gswin.gswindow:Connect(wx.wxEVT_ERASE_BACKGROUND, function (event) end)
+ gswin.gswindow:SetBackgroundStyle(wx.wxBG_STYLE_CUSTOM)
+
+ gswin.gswindow:Connect(wx.wxEVT_SIZE, function (event)
+ local size = event:GetSize()
+ ProcessResizeEvent(size:GetWidth(),size:GetHeight())
+ event:Skip()
+ end )
+
+ gswin.gswindow:Connect(wx.wxEVT_LEFT_DOWN, MouseButtonEvent)
+ gswin.gswindow:Connect(wx.wxEVT_LEFT_UP, MouseButtonEvent)
+ gswin.gswindow:Connect(wx.wxEVT_LEFT_DCLICK, MouseButtonEvent)
+ gswin.gswindow:Connect(wx.wxEVT_RIGHT_DOWN, MouseButtonEvent)
+ gswin.gswindow:Connect(wx.wxEVT_RIGHT_UP, MouseButtonEvent)
+ gswin.gswindow:Connect(wx.wxEVT_RIGHT_DCLICK, MouseButtonEvent)
+ gswin.gswindow:Connect(wx.wxEVT_MOUSEWHEEL, MouseWheelEvent)
+ gswin.gswindow:Connect(wx.wxEVT_MOTION, MouseMotionEvent)
+
+
+ PrepareKeyNames()
+
+ gswin.gswindow:Connect(wx.wxEVT_KEY_DOWN, function (event)
+ if not SendKeyEvent(event:GetKeyCode(),event:GetModifiers(),true) then event:Skip() end
+ end )
+ gswin.gswindow:Connect(wx.wxEVT_KEY_UP, function (event)
+ if not SendKeyEvent(event:GetKeyCode(),event:GetModifiers(),false) then event:Skip() end
+ end )
+ gswin.gswindow:Connect(wx.wxEVT_CHAR, function (event)
+ if not SendCharEvent(event) then event:Skip() end
+ end )
+
+end
+
+function InitializeConsole()
+ console=console:DynamicCast("wxFrame")
+ -- assume that console frame has one child, and this is TextCtrl !
+ gswin.logwindow = console:GetChildren():Item(0):GetData():DynamicCast("wxTextCtrl")
+ gswin.editwindow = wx.wxTextCtrl(console, wx.wxID_ANY, "",
+ wx.wxDefaultPosition, wx.wxDefaultSize, wx.wxTE_PROCESS_ENTER)
+ consolesizer=wx.wxBoxSizer(wx.wxVERTICAL)
+ consolesizer:Add(gswin.logwindow,1,wx.wxEXPAND)
+ consolesizer:AddSpacer(2)
+ consolesizer:Add(gswin.editwindow,0,wx.wxEXPAND)
+ console:SetSizerAndFit(consolesizer)
+ gswin.editwindow:SetFocus()
+
+ gswin.logwindow:Connect(wx.wxEVT_CHAR, function (event)
+ if event:GetKeyCode()==wx.WXK_RETURN then RunInputString()
+ else gswin.editwindow:EmulateKeyPress(event) end event:Skip()
+ end )
+ gswin.editwindow:Connect(wx.wxEVT_COMMAND_TEXT_ENTER, function (event)
+ RunInputString()
+ end )
+end
+
+function PSFName(name)
+ if not name or name=="" then return "","",0 end
+ local fname=wx.wxFileName(name)
+ fname:Normalize()
+ local resdir=fname:GetVolume() .. fname.GetVolumeSeparator() ..
+ fname:GetPath(wx.wxPATH_GET_SEPARATOR,wx.wxPATH_UNIX)
+ local resfn=fname:GetFullName(wx.wxPATH_UNIX)
+ return resdir,resfn,#resdir
+end
+
+function SetPSFile(fdir,fname)
+ gsargs.psf_dir, gsargs.psf_name = fdir,fname
+ SetPSTitle(fname)
+ if gsobj.instancechecker then gsobj.instancechecker:Destroy() end
+ gsobj.instancechecker = CreateInstanceChecker()
+ gsobj.instancechecker:IsAnotherInstance()
+end
+
+function SetPSTitle(fname)
+ local wtitle=PS_VIEW_NAME
+ if fname~="" then wtitle=fname .. " -- " .. wtitle end
+ frame:SetTitle(wtitle)
+ if console then console:SetTitle(wtitle .. _T(" Console")) end
+end
+
+function PrintUsageInfo(appname,luaname)
+ print(_T("This is ") .. PS_VIEW_VERSION_STRING .. _T(" working on wxLuaGhostscript;\n"))
+ print(_T("built with ") .. wxlua.wxLUA_VERSION_STRING .. _T(" and ") .. wx.wxVERSION_STRING)
+ if gsobj.gsdll then
+ print(_T(";\nlinked with Ghostscript ") ..string.format("%g",gsobj.gsdll:GetVersion())) end
+ print(_T(".\n\nUsage: ") .. appname .. _T(" [-h|--help] [-c|--console] [-l|--lua] ")
+ .. luaname .. _T(" [options] [-p|--ps] PS_View.ps [-- [more options]]\n"))
+ print(_T(" -h, --help help on command line arguments;\n"))
+ print(_T(" -c, --console show message console;\n"))
+ print(_T(" -l, --lua wxLua script to construct application;\n"))
+ print(_T(" -p, --ps PostScript program to run;\n"))
+ print(_T(" -q, --quiet turn off most of messages;\n"))
+ print(_T(" -v, --verbose turn on verbose/debug mode and console;\n"))
+ print(_T(" -n, --new open new window for document;\n"))
+ print(_T(" -w, --watch watch for document changes;\n"))
+ print(_T(" -g, --gsdll path to Ghostscript .dll/.so file;\n"))
+ print(_T(" -i, --gslib paths to Ghostscript init files;\n"))
+ print(_T(" -s, --gsset ghostscript parameter (-s equivalent);\n"))
+ print(_T(" -d, --gsdef ghostscript parameter (-d equivalent);\n"))
+ print(_T(" -- all following argument will be directly passed to\n"))
+ print(_T(" Ghostscript before the PostScript (-p) program name;\n"))
+ if console then console:Show() end
+end
+
+function GetParameter(argt,i,short,long)
+ assert(argt[i],"Assertion falied -- parameter number out of range")
+ local _m,_p = argt[i]:match("^(%-"..short..")(.*)$")
+ if not _m then _m,_p = argt[i]:match("^(%-%-"..long..")(.*)$") end
+ if not _m then return false end
+ if _p=="" then return true
+ else
+ error(_T("Option: ") .. _m .. _T(" has a unexpected value: ") .. _p ..
+ _T("\nUse -h or --help option for usage.\n"))
+ end
+end
+
+function GetParameterValue(argt,i,short,long)
+ assert(argt[i],"Assertion falied -- parameter number out of range")
+ local _m,_p = argt[i]:match("^(%-"..short..")(.*)$")
+ if not _m then _m,_p = argt[i]:match("^(%-%-"..long..")(.*)$") end
+ if not _m then return false,0 end
+ if _p=="" then
+ local _n=argt[i+1]
+ if _n and _n:sub(1,1)~="-" then return _n,1
+ else
+ error(_T("Option: ") .. _m .. _T(" must have a value.") ..
+ _T("\nUse -h or --help option for usage.\n"))
+ end
+ else
+ return _p,0
+ end
+end
+
+function ParseCommandLine(argt)
+ if argt then
+ local function addgsarg(v) table.insert(gsargs.args, v) end
+ -- arguments pushed into wxLua are
+ -- [C++ app and it's args][lua prog at 0][args for lua start at 1]
+ local n,to_gs,psf_name = 0,false,nil
+ while argt[n-1] do n = n - 1 end
+
+ -- n == exe program name
+ local i,_v,_i=n+1
+ repeat
+ print_debug("args: ", i, argt[i], "\n")
+ _v,_i=false,0
+ -- 0 == this program name
+ if i==0 then _v=true end
+ if to_gs then
+ _v=argt[i] addgsarg(_v)
+ end
+ if argt[i]=="--" then
+ to_gs=true
+ _v=true
+ assert(i>0,"Assert failed -- parameter passing error")
+ end
+ if not _v then
+ _v = GetParameter(argt,i,"h","help")
+ if _v then
+ PrintUsageInfo(arg[n],arg[0])
+ return false
+ end
+ end
+ if not _v then
+ _v = GetParameter(argt,i,"c","console")
+ -- console parameter already processed
+ end
+ if not _v then
+ _v = GetParameter(argt,i,"q","quiet")
+ if _v then verbose=v_quiet
+ addgsarg("-q") -- -q implies also quiet Ghostscript
+ end
+ end
+ if not _v then
+ _v = GetParameter(argt,i,"v","verbose")
+ if _v then verbose=v_verbose
+ if console then console:Show() end -- -v implies -c
+ end
+ end
+ if not _v then
+ _v,_i = GetParameterValue(argt,i,"l","lua")
+ -- lua parameter already processed -- check only for bad usage
+ if _v then
+ if i>0 then
+ error(_T("Only one wxLua script can be run -- superfluous: ") .. arg[i]
+ .. _T(" parameter.") ..
+ _T("\nUse -h or --help option for usage.\n"))
+ end
+ assert(i==-1,"Assert failed -- parameter passing error")
+ end
+ end
+ if not _v then
+ _v = GetParameter(argt,i,"n","new")
+ if _v then force_open=true end
+ end
+ if not _v then
+ _v,_i = GetParameterValue(argt,i,"g","gsdll")
+ if _v then
+ if gsargs.dllloc~="" then
+ print_message(_T("Warning -- parameter: ") .. argt[i] .. _T(" overrides previous value.\n"))
+ end
+ gsargs.dllloc=_v
+ end
+ end
+ if not _v then
+ _v,_i = GetParameterValue(argt,i,"i","gslib")
+ if _v then table.insert(gsargs.libs,_v) end
+ end
+ if not _v then
+ _v,_i = GetParameterValue(argt,i,"s","gsset")
+ if _v then addgsarg("-s".._v)
+ if _v:find("INPUT[=#]") then psf_name=_v:match("INPUT[=#](.+)") end
+ end
+ end
+ if not _v then
+ _v,_i = GetParameterValue(argt,i,"d","gsdef")
+ if _v then addgsarg("-d".._v) end
+ end
+ if not _v then
+ _v,_i = GetParameterValue(argt,i,"p","ps")
+ if _v then table.insert(gsargs.progs,_v) end
+ end
+ if not _v then
+ if not argt[i]:match("^%-") then
+ _v=argt[i] table.insert(gsargs.progs, _v)
+ end
+ end
+ if not _v then
+ error(_T("Unrecognized option: ") .. argt[i] ..
+ _T("\nUse -h or --help option for usage.\n"))
+ end
+ i=i+1+_i
+ until i > #argt
+ -- and try to find name of file to be opened
+ -- (it is used for window title, and refresh mechanism
+ if psf_name then gsargs.psf_dir, gsargs.psf_name = PSFName(psf_name) end
+ end
+ return true
+end
+
+function FixGSPaths(gsargs)
+ local libloc, gslib, psvlib = gsargs.libloc, gsargs.gslib, gsargs.psvlib
+ local libstr, sep, fname = "", ":", wx.wxFileName()
+ if wx.__WXMSW__ or wx.__WXOS2__ then sep=";"
+ elseif wx.__WXMAC__ then sep="," end
+
+ if gsargs.dllloc=="" and os.getenv("GS_DLL") then
+ gsargs.dllloc=os.getenv("GS_DLL") end
+ if gsargs.fontloc=="" and os.getenv("GS_FONTS") then
+ gsargs.fontloc=os.getenv("GS_FONTS") end
+
+ if gslib=="" then
+ if gsargs.dllloc~="" then
+ fname:Assign(gsargs.dllloc)
+ fname:RemoveDir(fname:GetDirCount()-1) fname:AppendDir("lib")
+ fname:SetName("gs_init") fname:SetExt("ps")
+ if fname:FileExists() then gslib = PSFName(fname:GetFullPath()) end
+ end
+ end
+
+ if psvlib=="" then
+ for i,v in ipairs(gsargs.progs) do
+ fname:Assign(v)
+ if fname:FileExists() then
+ if fname:IsAbsolute() then psvlib = PSFName(fname:GetFullPath()) end
+ else
+ fname:Assign(wx.wxFileName(arg[0]):GetPath(wx.wxPATH_GET_VOLUME),v)
+ if fname:FileExists() then psvlib = PSFName(fname:GetFullPath()) end
+ end
+ end
+ end
+
+ for i,v in ipairs(gsargs.libs) do
+ if libstr~="" then libstr=libstr..sep..v else libstr=v end
+ end
+ if libstr=="" and libloc~="" then libstr=gslibloc end
+
+ if gslib~="" and not libstr:find(gslib,1,true) then
+ if libstr~="" then libstr=gslib..sep..libstr else libstr=gslib end
+ end
+ if psvlib~="" and not libstr:find(psvlib,1,true) then
+ if libstr~="" then libstr=libstr..sep..psvlib else libstr=psvlib end
+ end
+
+ if libstr=="" and os.getenv("GS_LIB") then libstr=os.getenv("GS_LIB") end
+
+ gsargs.libloc, gsargs.gslib, gsargs.psvlib = libstr, gslib, psvlib
+
+ -- add default parameters at begining
+ for i,v in ipairs(gsargs.dftpars) do table.insert(gsargs.args,i,v) end
+ -- and PS programs at the end
+ for i,v in ipairs(gsargs.progs) do table.insert(gsargs.args,v) end
+end
+
+
+function SetLocale(lang)
+ local progdir=wx.wxFileName(arg[0]):GetPath(wx.wxPATH_GET_VOLUME)
+ if progdir=="" then progdir="." end
+ gsobj.locale=wx.wxLocale(lang)
+ os.setlocale("C","numeric")
+ if gsobj.locale:IsOk() then
+ gsobj.locale.AddCatalogLookupPathPrefix(progdir)
+ gsobj.locale:AddCatalog("psv") -- locale `domain'
+ end
+end
+
+function PrepareLocale()
+ local lang=wx.wxLANGUAGE_DEFAULT
+ if psvpars.language~="" then
+ local langinf=wx.wxLocale.FindLanguageInfo(psvpars.language)
+ if langinf then lang=langinf.Language end
+ end
+ SetLocale(lang)
+-- trans=io.open("trans.txt","a")
+ function _T(str)
+-- trans:write("msgid: \""..str.."\"\n")
+ return wx.wxGetTranslation(str)
+ end
+ PS_VIEW_VERSION_STRING=string.format(_T("%s, version %g"), PS_VIEW_NAME, PS_VIEW_VERSION)
+end
+
+function CreateInstanceChecker()
+ local checker={}
+ function checker:Create()
+ -- wx.wxFileName.GetTempDir() -- not implemented in wxLua
+ -- os.tmpname() -- gives bad result under MSW
+ local fname=wx.wxFileName()
+ fname:AssignTempFileName("." .. PS_VIEW_NAME)
+ if fname:IsOk() then
+ wx.wxRemoveFile(fname:GetFullPath())
+ else return false end
+ fname:AssignDir(fname:GetPath(wx.wxPATH_GET_VOLUME))
+ fname:AppendDir("." .. PS_VIEW_NAME)
+ if not fname:DirExists() then
+ if not fname:Mkdir() then return false end
+ end
+ self.dname=wx.wxFileName(fname)
+ fname:SetName("." .. PS_VIEW_NAME .. MakeNameHash()) fname:SetExt("lock")
+ self.fname=wx.wxFileName(fname)
+ self.created=false self.time=nil
+ end
+--
+ function checker:SetTime()
+ local ok,modtime=self.fname:GetTimes()
+ if ok then self.time=modtime end
+ end
+ function checker:CheckTime()
+ local ok,modtime=self.fname:GetTimes()
+ if modtime:IsLaterThan(self.time) then
+ self.time=modtime return true
+ else return false end
+ end
+ function checker:CreateLock()
+ local file=wx.wxFile(self.fname:GetFullPath(),wx.wxFile.write)
+ if file:IsOpened() then
+ file:Write(tostring(wx.wxGetProcessId())) file:Close()
+ end
+ self:SetTime() self.created=true
+ end
+ function checker:UpdateLock()
+ self.fname:Touch()
+ self:SetTime()
+ end
+--
+ function checker:IsAnotherInstance()
+ if not self.dname or not self.fname then return false end
+ if not self.dname:DirExists() then self.dname:Mkdir() end
+ if self.fname:FileExists() then
+ self:UpdateLock() return true
+ else
+ self:CreateLock() return false
+ end
+ end
+--
+ function checker:IsLockUpdated()
+ if not self.dname or not self.fname then return false end
+ if not self.dname:DirExists() then self.dname:Mkdir() end
+ if self.fname:FileExists() then
+ return self:CheckTime()
+ else
+ self:CreateLock() return true
+ end
+ end
+--
+ function checker:Destroy()
+ if not self.dname or not self.fname then return false end
+ if not self.dname:DirExists() then return false end
+ if self.created and self.fname:FileExists() then
+ wx.wxRemoveFile(self.fname:GetFullPath())
+ end
+ local old,mod=wx.wxDateTime(os.time())
+ old:Subtract(wx.wxDateSpan.Days(7))
+ local dir=wx.wxDir(self.dname:GetPath(wx.wxPATH_GET_VOLUME))
+ local f,filen=dir:GetFirst()
+ local fname=wx.wxFileName(dir:GetName(),filen)
+ while f do
+ ok,mod=fname:GetTimes()
+ if mod:IsEarlierThan(old) then wx.wxRemoveFile(fname:GetFullPath()) end
+ f,filen=dir:GetNext() fname:SetFullName(filen)
+ end
+ if not dir:HasFiles() then wx.wxRmdir(dir:GetName()) end
+ self.dname=nil self.fname=nil self.time=nil
+ return true
+ end
+--
+ checker:Create()
+ return checker
+end
+
+function MakeNameHash()
+ local str = PS_VIEW_NAME .. wx.wxGetUserId() .. gsargs.psf_dir .. gsargs.psf_name
+ local hash,hasht = 231172,{}
+ for i,v in ipairs{str:byte(1,#str)} do hash = hash + 8^(i%13)*v end
+ while hash>1 do table.insert(hasht,65+hash%26%26) hash=math.floor(hash/26) end
+ return string.char(unpack(hasht))
+end
+
+function ConfigGetParameters()
+ gsobj.config:SetPath("/PSV_Parameters")
+ local _, _cmd = gsobj.config:Read("cmdpars", "")
+ local _, _lang = gsobj.config:Read("language", "")
+ if psvpars.cmd_pars=="" and _cmd then psvpars.cmd_pars = _cmd end
+ if psvpars.language=="" and _lang then psvpars.language = _lang end
+end
+
+function ConfigGetPaths(gsargs)
+ gsobj.config:SetPath("/GhostscriptPaths")
+ local _, _gsdll = gsobj.config:Read("dll", "")
+ local _, _gslibs = gsobj.config:Read("libs", "")
+ local _, _gsfont = gsobj.config:Read("font", "")
+ local _, _gslib = gsobj.config:Read("gslib", "")
+ local _, _psvlib = gsobj.config:Read("psvlib", "")
+ if gsargs.dllloc=="" and _gsdll then gsargs.dllloc =_gsdll end
+ if gsargs.libloc=="" and _gslibs then gsargs.libloc =_gslibs end
+ if gsargs.fontloc=="" and _gsfont then gsargs.fontloc=_gsfont end
+ if gsargs.gslib=="" and _gslib then gsargs.gslib =_gslib end
+ if gsargs.psvlib=="" and _psvlib then gsargs.psvlib =_psvlib end
+end
+
+function ConfigSavePaths(gsargs)
+ gsobj.config:SetPath("/GhostscriptPaths")
+ gsobj.config:Write("dll", gsargs.dllloc)
+ gsobj.config:Write("libs", gsargs.libloc)
+ gsobj.config:Write("font", gsargs.fontloc)
+ gsobj.config:Write("gslib", gsargs.gslib)
+ gsobj.config:Write("psvlib", gsargs.psvlib)
+end
+
+function ConfigRestoreFramePosition(window, windowName)
+ gsobj.config:SetPath("/"..windowName)
+ local _, s = gsobj.config:Read("s", -1)
+ local _, x = gsobj.config:Read("x", -1)
+ local _, y = gsobj.config:Read("y", -1)
+ local _, w = gsobj.config:Read("w", -1)
+ local _, h = gsobj.config:Read("h", -1)
+ if s ~= -1 then
+ local cX, cY, cW, cH = wx.wxClientDisplayRect()
+ if x < cX then x = cX end
+ if y < cY then y = cY end
+ if w > cW then w = cW end
+ if h > cH then h = cH end
+ window:SetSize(x, y, w, h)
+ end
+ if s == 1 then window:Maximize(true) end
+end
+
+function ConfigSaveFramePosition(window, windowName)
+ gsobj.config:SetPath("/"..windowName)
+ local s = 0
+ local w, h = window:GetSizeWH()
+ local x, y = window:GetPositionXY()
+
+ if window:IsMaximized() then s = 1
+ elseif window:IsIconized() then s = 2 end
+ gsobj.config:Write("s", s)
+ if s == 0 then
+ gsobj.config:Write("x", x)
+ gsobj.config:Write("y", y)
+ gsobj.config:Write("w", w)
+ gsobj.config:Write("h", h)
+ end
+end
+
+function Main()
+ wxapp = wx.wxGetApp()
+ console=wxapp:GetTopWindow() -- or `nil' if console not created
+ wxapp:SetAppName("psv")
+
+ gsobj.config = wx.wxFileConfig() -- default setting are very nice
+ ConfigGetParameters()
+ PrepareLocale()
+
+ if not ParseCommandLine(arg) then return true end
+
+ if #gsargs.progs==0 then
+ error(_T("No PostScript programe give in commandline, I don't know what to do -- quiting.\n"))
+ end
+
+ gsobj.instancechecker = CreateInstanceChecker()
+ if not gsobj.instancechecker then
+ error(_T("Unable to create instance checker, check lock in temp directory -- quiting.\n"))
+ end
+ if gsobj.instancechecker:IsAnotherInstance() and not force_open then
+ print_message(_T("Another instance of PS_View is running -- quiting.\n"))
+ gsobj.instancechecker:Destroy()
+ return true
+ elseif force_open then gsobj.instancechecker.created=true end
+
+
+ ConfigGetPaths(gsargs)
+
+ -- create the wxFrame window
+ frame = wx.wxFrame( wx.NULL, -- no parent for toplevel windows
+ wx.wxID_ANY, -- don't need a wxWindow ID
+ PS_VIEW_NAME, -- caption on the frame
+ wx.wxDefaultPosition, -- let system place the frame
+ wx.wxDefaultSize, -- set the size of the frame
+ wx.wxDEFAULT_FRAME_STYLE ) -- use default frame styles
+
+ ConfigRestoreFramePosition(frame, "MainWindow")
+ frame:SetIcons(iconimg)
+
+ if console then
+ InitializeConsole()
+ ConfigRestoreFramePosition(console, "ConsoleWindow")
+ console:SetIcons(icontxt)
+ wxapp:SetTopWindow(frame)
+ end
+
+ SetPSTitle(gsargs.psf_name)
+
+ FixGSPaths(gsargs)
+
+ InitializeGS()
+ StartGS()
+
+ ConnectEvents ()
+
+ -- show the frame window
+ frame:Show(true)
+ gswin.gswindow:SetFocus()
+
+ wx.wxWakeUpIdle() -- probably not needed, but inserted for sure
+end
+
+
+Main()