'-------------------------------------------------------------------------------- ' 'exe2unix.inc' v0.4 for PBWin9 - Facilitates the usage of Windows .exe in Linux '-------------------------------------------------------------------------------- DECLARE FUNCTION Exe2Unix(BYVAL src AS STRING, BYVAL showInAppMenu AS LONG, _ OPTIONAL BYVAL dkpName AS STRING) AS LONG ' - extract exe icon, convert it to png, copy it to ~/.local/share/icons ' - create a .desktop entry in ~/.local/share/applications to show icon in dock ' - if 'showInAppMenu' is true, add the program in the XDG Desktop Menu ' - use 'gio set' to apply the icon to the exe in the Linux file explorer DECLARE SUB Me2Unix(BYVAL askConfirmation AS LONG, BYVAL showInAppMenu AS LONG, _ OPTIONAL BYVAL dkpName AS STRING) ' - exact same as Exe2Unix() but applied to ourselves when compiled into an exe DECLARE FUNCTION Exe2UnixConfirm(BYVAL src AS STRING) AS LONG ' - ask user confirmation to register the exe in the Linux App Menu, ' result is either %IDYES or %IDNO DECLARE FUNCTION IcoStrip2Unix(BYVAL src AS STRING) AS STRING ' - extract an exe icon, convert it to png, copy it to ~/.local/share/icons DECLARE SUB FileIco2Unix(BYVAL src AS STRING, BYVAL png AS STRING) ' - apply an icon (png) to a file in the Linux file explorer '-------------------------------------------------------------------------------- '-------------------------------------------------------------------------------- #INCLUDE ONCE "Gdiplus.inc" ' from JoseRoca includes #INCLUDE ONCE "GdipUtils.inc" ' from JoseRoca includes #INCLUDE ONCE "inc/icostrip.inc" #INCLUDE ONCE "inc/unix.inc" '-------------------------------------------------------------------------------- MACRO UNIX_SHARE = UNIX_HOME + ".local\share\" '-------------------------------------------------------------------------------- MACRO UNIX_XPATH = UnixPath(LTRIM$(EXE.PATH$, "\")) '-------------------------------------------------------------------------------- MACRO UNIX_DESKTOP(x) = UNIX_SHARE+"applications\wine-"+UnixSafeName(x)+".desktop" '-------------------------------------------------------------------------------- '-------------------------------------------------------------------------------- FUNCTION Exe2Unix(BYVAL src AS STRING, BYVAL showInAppMenu AS LONG, _ OPTIONAL BYVAL dkpName AS STRING) AS LONG ' Register a windows executable as a Linux App: ' - extract its icon, convert it to png, copy it to ~/.local/share/icons ' - create a .desktop entry in ~/.local/share/applications to show and launch ' the program from the XDG Desktop Menu ' - customize the .exe itself to display its icon in Linux file explorer LOCAL ff AS LONG LOCAL lRes AS LONG LOCAL png AS STRING LOCAL wmc AS STRING LOCAL xec AS STRING LOCAL dkp AS STRING FUNCTION = 0 ' by default ' Extract exe icon and convert to png in ~/.local/share/icons png = IcoStrip2Unix(src) ' Set the program icon to the executable itself in Linux file explorer FileIco2Unix src, png ' Create the .desktop fields IF LEN(dkpName) THEN dkp = UNIX_DESKTOP(dkpName) ELSE dkp = UNIX_DESKTOP(src) END IF wmc = LCASE$(PATHNAME$(NAMEX, src)) xec = "env WINEPREFIX=" + $DQ xec += "/home/" + ENVIRON$("USERNAME") xec += "/.wine" + $DQ + " wine " xec += UnixProtect(src) ' Create .desktop file for the exe in ~/.local/share/applications ff = FREEFILE OPEN dkp FOR OUTPUT AS #ff PRINT #ff, "[Desktop Entry]" PRINT #ff, "Name=" + PATHNAME$(NAME, src) PRINT #ff, "StartupWMClass=" + wmc IF ISTRUE showInAppMenu THEN PRINT #ff, "Exec=" + xec ELSE PRINT #ff, "NoDisplay=true" END IF PRINT #ff, "Type=Application" PRINT #ff, "Terminal=false" PRINT #ff, "StartupNotify=true" PRINT #ff, "Icon=" + PATHNAME$(NAME, png) CLOSE #ff ' Set the program icon to the .desktop file too, for user friendliness FileIco2Unix dkp, png ' Done! FUNCTION = 1 END FUNCTION '-------------------------------------------------------------------------------- '-------------------------------------------------------------------------------- SUB Me2Unix(BYVAL askConfirmation AS LONG, BYVAL showInAppMenu AS LONG, _ OPTIONAL BYVAL dkpName AS STRING) LOCAL ff, lRes AS LONG LOCAL xPath AS STRING LOCAL dPath AS STRING LOCAL zText AS ASCIIZ * 255 ' No need to go further if we're not on Unix IF NOT IsOnUnix() THEN EXIT SUB ' In any case, reveal the exe icon in Nautilus FileIco2Unix EXE.FULL$, IcoStrip2Unix(EXE.FULL$) ' Check any existing .dekstop file IF LEN(dkpName) THEN dPath = UNIX_DESKTOP(dkpName) ELSE dPath = UNIX_DESKTOP(EXE.FULL$) END IF IF EXISTS(dPath) THEN EXIT SUB ' Ask user confirmation if needed xPath = EXE.FULL$ IF ISTRUE askConfirmation THEN lRes = MyMsgBox(0, "Do you want to register this program as a Linux App?" + $CRLF _ + "(it will be listed in the XDG Desktop Menu for quick access)" _ , EXE.NAME$, %MB_ICONQUESTION + %MB_YESNO) IF lRes = %IDNO THEN EXIT SUB IF LCASE$(EXE.PATH$) <> "c:\apps\" THEN lRes = MyMsgBox(0, "We recommend to have Windows executables stored in the " _ + "'~/.wine/drive_c/Apps' folder. Would you like to move this " _ + "program there, or do you prefer to launch it from " _ + "'" + UNIX_XPATH + "' ?" + $CR _ + "(beware that in this case, moving it in the future will break " _ + "the Linux App shortcut in the Desktop Menu)." + $CR + $CR _ + "- Click Yes to move to '~/.wine/drive_c/Apps'" + $CR + $CR _ + "- Click No to keep in '" + UNIX_XPATH + "'" + $CR + $CR _ + "- Click Cancel to abandon registration as a Linux App." _ , EXE.NAME$, %MB_ICONQUESTION + %MB_YESNOCANCEL) IF lRes = %IDCANCEL THEN EXIT SUB IF lRes = %IDYES THEN MKDIR "C:\Apps" FILECOPY EXE.FULL$, "C:\Apps\" + EXE.NAMEX$ xPath = "C:\Apps\" + EXE.NAMEX$ END IF END IF END IF ' Register! lRes = Exe2Unix(xPath, showInAppMenu, dkpName) IF askConfirmation AND lRes <= 0 THEN MyMsgBox(0, "An error occured." + $CRLF _ +"Registration failed." + $CRLF + $CRLF _ +"Click OK to continue the program." _ , EXE.NAME$, %MB_ICONWARNING) EXIT SUB END IF ' Special case: exe moved, create batch file to delete old exe and restart in C:\Apps IF askConfirmation AND xPath <> EXE.FULL$ THEN ff = FREEFILE OPEN ENVIRON$("TEMP") + "\" + EXE.NAME$ + ".bat" FOR OUTPUT AS #ff PRINT #ff, "TimeOut 1" PRINT #ff, "del " + $DQ + EXE.FULL$ + $DQ PRINT #ff, "start " + $DQ+$DQ + $SPC + $DQ+xPath+$DQ CLOSE #ff ff = SHELL(ENVIRON$("TEMP") + "\" + EXE.NAME$ + ".bat", 0) ExitProcess(12345) ' Close ourselves END IF END SUB '-------------------------------------------------------------------------------- '-------------------------------------------------------------------------------- FUNCTION Exe2UnixConfirm(BYVAL src AS STRING) AS LONG ' Ask user confirmation to register the exe in the Linux App Menu ' Result is either %IDYES or %IDNO LOCAL lRes AS LONG lRes = MyMsgBox(0, "Would you like to register " _ + $DQ + PATHNAME$(NAMEX,src) + $DQ _ + " as a Linux App and launch it from " _ + PATHNAME$(PATH,src) + " ?", EXE.NAME$ _ , %MB_ICONQUESTION + %MB_YESNO) FUNCTION = lRes END FUNCTION '-------------------------------------------------------------------------------- '-------------------------------------------------------------------------------- FUNCTION IcoStrip2Unix(BYVAL src AS STRING) AS STRING ' - extract an exe icon, convert it to png, copy it to ~/.local/share/icons LOCAL ico AS STRING LOCAL png AS STRING LOCAL hIcon AS DWORD LOCAL pImage AS DWORD LOCAL i, j AS LONG ' Does the executable icon in png format already exist in ~/.local/share/icons? ico = UNIX_SHARE + "icons\" + UnixSafeName(src) + ".ico" png = LEFT$(ico, -4) + ".png" IF EXISTS(png) THEN FUNCTION = png : EXIT FUNCTION ' If not, extract exe's main icon IF NOT EXISTS(ico) THEN IF IcoStrip(src, 1, ico) <= 0 THEN ' extraction failed FUNCTION = "" EXIT FUNCTION END IF END IF ' Convert executable icon to png ' UnixShell "convert " _ ' + "~/.local/share/icons/"+UnixSafeName(src)+".ico " _ ' + "~/.local/share/icons/"+UnixSafeName(src)+".png" hIcon = LoadImage(0, BYVAL STRPTR(ico), %IMAGE_ICON, gsIcoRes, gsIcoRes, %LR_LOADFROMFILE) GdipCreateBitmapFromHICON hIcon, pImage GdipConvertToPng pImage, png ' Conversion to png worked (single resolution icon) IF EXISTS(png) THEN FUNCTION = png : EXIT FUNCTION ' Conversion produced several resolution png's IF EXISTS(LEFT$(png,-4)+"-0.png") THEN DO INCR i LOOP UNTIL NOT EXISTS(LEFT$(png,-4)+"-"+FORMAT$(i)+".png") DECR i ' final index for highest resolution png NAME LEFT$(png,-4)+"-"+FORMAT$(i)+".png" _ AS LEFT$(png,-4)+".png" FOR j = 0 TO i-1 KILL LEFT$(png,-4)+"-"+FORMAT$(j)+".png" NEXT FUNCTION = png EXIT FUNCTION END IF ' Conversion didn't produce any png > use ico instead FUNCTION = ico END FUNCTION '-------------------------------------------------------------------------------- '-------------------------------------------------------------------------------- SUB FileIco2Unix(BYVAL src AS STRING, BYVAL png AS STRING) ' - customize a file in Linux file explorer to display an icon (png) LOCAL xec AS STRING xec = "gio set -t 'string' '" + UnixPath(src) + "' " xec += "'metadata::custom-icon' " xec += "'file://" + UnixPath(png) + "'" UnixShell xec END SUB '-------------------------------------------------------------------------------- '-------------------------------------------------------------------------------- #IF NOT %DEF(%FN_EXISTS) %FN_EXISTS = -1 FUNCTION EXISTS(BYVAL f AS STRING) AS LONG LOCAL i AS LONG i = GETATTR(f) FUNCTION = (ERRCLEAR = 0) END FUNCTION #ENDIF '-------------------------------------------------------------------------------- '-------------------------------------------------------------------------------- FUNCTION UnixSafeName(BYVAL xpath AS STRING) AS STRING ' Define a safe filename for a windows executable, for use in unix LOCAL r AS STRING r = PATHNAME$(NAME, xpath) r = LCASE$(REMOVE$(r, " ")) FUNCTION = r END FUNCTION '-------------------------------------------------------------------------------- '-------------------------------------------------------------------------------- FUNCTION UnixProtect(BYVAL str AS STRING) AS STRING LOCAL r AS STRING r = str REPLACE "\" WITH "\\\\" IN r REPLACE " " WITH "\\ " IN r FUNCTION = r END FUNCTION '-------------------------------------------------------------------------------- '-------------------------------------------------------------------------------- SUB GdipConvertToPng(BYVAL pImage AS DWORD, BYVAL srcImg AS STRING) LOCAL hStatus AS LONG LOCAL token AS DWORD LOCAL StartupInput AS GdiplusStartupInput ' Initialize GDI+ StartupInput.GdiplusVersion = 1 hStatus = GdiplusStartup(token, StartupInput, BYVAL %NULL) IF hStatus THEN ' ?"Error initializing GDI+",%MB_ICONERROR,EXE.NAME$ EXIT SUB END IF ' Call conversion function GdiPlusSaveImageToPng pImage, srcImg ' Shutdown GDI+ GdiplusShutdown token END SUB '--------------------------------------------------------------------------------