From 26e5f1a8ec3eb2952e49c87c91395fdcdceddfe9 Mon Sep 17 00:00:00 2001 From: Georg Baum Date: Tue, 21 Feb 2012 20:29:44 +0000 Subject: [PATCH] Use libmagic for file format detection if available. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@40789 a592a061-630c-0410-9148-cb99ea01b6c8 --- RELEASE-NOTES | 5 +- configure.ac | 10 ++ lib/configure.py | 170 +++++++++++----------- lib/doc/Customization.lyx | 40 ++++- lib/scripts/prefs2prefs_prefs.py | 84 ++++++++++- src/Buffer.cpp | 2 +- src/Format.cpp | 75 +++++++++- src/Format.h | 20 ++- src/Lexer.cpp | 11 +- src/LyXRC.cpp | 52 ++++--- src/frontends/qt4/GuiPrefs.cpp | 10 +- src/frontends/qt4/GuiPrefs.h | 1 + src/frontends/qt4/ui/PrefFileformatsUi.ui | 14 ++ src/graphics/epstools.cpp | 6 +- src/support/FileName.cpp | 7 - src/support/FileName.h | 3 - 16 files changed, 370 insertions(+), 140 deletions(-) diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 28f9aedd06..50c1cf8ecc 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -68,7 +68,10 @@ into the tarball. New external programs and libraries: ------------------------------------ -- +- LyX links now against libmagic (http://www.darwinsys.com/file/) if it is + available at compile time. This improves the file format detection of + included graphics and other files. The old builtin format detection code + is used if libmagic is not available. Known issues in version 2.1.0 diff --git a/configure.ac b/configure.ac index c4f1ebeb31..acfa66338e 100644 --- a/configure.ac +++ b/configure.ac @@ -115,6 +115,16 @@ AC_CHECK_HEADERS(zlib.h, [AC_CHECK_LIB(z, gzopen, [LIBS="$LIBS -lz"], LYX_LIB_ERROR(libz,zlib))], [LYX_LIB_ERROR(zlib.h,zlib)]) +### check for file magic support (currently optional) +AC_CHECK_HEADERS(magic.h, + [AC_CHECK_LIB(magic, magic_open, [LIBS="$LIBS -lmagic"], + LYX_WARNING([Cannot find limagic. Please check that the libmagic library + is correctly installed on your system. + Falling back to builtin file format detection.]))], + [LYX_WARNING([Cannot find magic.h. Please check that the libmagic library + is correctly installed on your system. + Falling back to builtin file format detection.])]) + ### check which frontend we want to use diff --git a/lib/configure.py b/lib/configure.py index 80acf6572b..ae987ef63f 100644 --- a/lib/configure.py +++ b/lib/configure.py @@ -480,36 +480,36 @@ def checkModule(module): def checkFormatEntries(dtl_tools): ''' Check all formats (\Format entries) ''' checkViewerEditor('a Tgif viewer and editor', ['tgif'], - rc_entry = [r'\Format tgif obj Tgif "" "%%" "%%" "vector"']) + rc_entry = [r'\Format tgif "obj, tgo" Tgif "" "%%" "%%" "vector" "application/x-tgif"']) # checkViewerEditor('a FIG viewer and editor', ['xfig', 'jfig3-itext.jar', 'jfig3.jar'], - rc_entry = [r'\Format fig fig FIG "" "%%" "%%" "vector"']) + rc_entry = [r'\Format fig fig FIG "" "%%" "%%" "vector" "application/x-xfig"']) # checkViewerEditor('a Dia viewer and editor', ['dia'], - rc_entry = [r'\Format dia dia DIA "" "%%" "%%" "vector,zipped=native"']) + rc_entry = [r'\Format dia dia DIA "" "%%" "%%" "vector,zipped=native", "application/x-dia-diagram"']) # checkViewerEditor('an OpenOffice drawing viewer and editor', ['libreoffice', 'lodraw', 'ooffice', 'oodraw', 'soffice'], - rc_entry = [r'\Format odg "odg, sxd" "OpenOffice drawing" "" "%%" "%%" "vector,zipped=native"']) + rc_entry = [r'\Format odg "odg, sxd" "OpenOffice drawing" "" "%%" "%%" "vector,zipped=native" "application/vnd.oasis.opendocument.graphics"']) # checkViewerEditor('a Grace viewer and editor', ['xmgrace'], - rc_entry = [r'\Format agr agr Grace "" "%%" "%%" "vector"']) + rc_entry = [r'\Format agr agr Grace "" "%%" "%%" "vector" ""']) # checkViewerEditor('a FEN viewer and editor', ['xboard -lpf $$i -mode EditPosition'], - rc_entry = [r'\Format fen fen FEN "" "%%" "%%" ""']) + rc_entry = [r'\Format fen fen FEN "" "%%" "%%" "" ""']) # checkViewerEditor('a SVG viewer and editor', ['inkscape'], - rc_entry = [r'\Format svg svg SVG "" "%%" "%%" "vector"']) + rc_entry = [r'\Format svg svg SVG "" "%%" "%%" "vector" "image/svg+xml"']) # - imageformats = r'''\Format bmp bmp BMP "" "%s" "%s" "" -\Format gif gif GIF "" "%s" "%s" "" -\Format jpg "jpg, jpeg" JPEG "" "%s" "%s" "" -\Format pbm pbm PBM "" "%s" "%s" "" -\Format pgm pgm PGM "" "%s" "%s" "" -\Format png png PNG "" "%s" "%s" "" -\Format ppm ppm PPM "" "%s" "%s" "" -\Format tiff tif TIFF "" "%s" "%s" "" -\Format xbm xbm XBM "" "%s" "%s" "" -\Format xpm xpm XPM "" "%s" "%s" ""''' + imageformats = r'''\Format bmp bmp BMP "" "%s" "%s" "" "image/x-bmp" +\Format gif gif GIF "" "%s" "%s" "" "image/gif" +\Format jpg "jpg, jpeg" JPEG "" "%s" "%s" "" "image/jpeg" +\Format pbm pbm PBM "" "%s" "%s" "" "image/x-portable-bitmap" +\Format pgm pgm PGM "" "%s" "%s" "" "image/x-portable-graymap" +\Format png png PNG "" "%s" "%s" "" "image/x-png" +\Format ppm ppm PPM "" "%s" "%s" "" "image/x-portable-pixmap" +\Format tiff tif TIFF "" "%s" "%s" "" "image/tiff" +\Format xbm xbm XBM "" "%s" "%s" "" "image/x-xbitmap" +\Format xpm xpm XPM "" "%s" "%s" "" "image/x-xpixmap"''' path, iv = checkViewerNoRC('a raster image viewer', ['xv', 'kview', 'gimp-remote', 'gimp'], rc_entry = [imageformats]) path, ie = checkEditorNoRC('a raster image editor', ['gimp-remote', 'gimp'], rc_entry = [imageformats]) addToRC(imageformats % \ @@ -517,102 +517,102 @@ def checkFormatEntries(dtl_tools): # checkViewerEditor('a text editor', ['xemacs', 'gvim', 'kedit', 'kwrite', 'kate', \ 'nedit', 'gedit', 'notepad'], - rc_entry = [r'''\Format asciichess asc "Plain text (chess output)" "" "" "%%" "" -\Format asciiimage asc "Plain text (image)" "" "" "%%" "" -\Format asciixfig asc "Plain text (Xfig output)" "" "" "%%" "" -\Format dateout tmp "date (output)" "" "" "%%" "" -\Format docbook sgml DocBook B "" "%%" "document,menu=export" -\Format docbook-xml xml "DocBook (XML)" "" "" "%%" "document,menu=export" -\Format dot dot "Graphviz Dot" "" "" "%%" "vector" -\Format dviluatex tex "LaTeX (dviluatex)" "" "" "%%" "document,menu=export" -\Format platex tex "LaTeX (pLaTeX)" "" "" "%%" "document,menu=export" -\Format literate nw NoWeb N "" "%%" "document,menu=export" -\Format sweave Rnw "Sweave" S "" "%%" "document,menu=export" -\Format r R "R/S code" "" "" "%%" "document,menu=export" -\Format knitr Rnw "Rnw (knitr)" "" "" "%%" "document,menu=export" -\Format lilypond ly "LilyPond music" "" "" "%%" "vector" -\Format lilypond-book lytex "LilyPond book (LaTeX)" "" "" "%%" "document,menu=export" -\Format latex tex "LaTeX (plain)" L "" "%%" "document,menu=export" -\Format luatex tex "LaTeX (LuaTeX)" "" "" "%%" "document,menu=export" -\Format pdflatex tex "LaTeX (pdflatex)" "" "" "%%" "document,menu=export" -\Format xetex tex "LaTeX (XeTeX)" "" "" "%%" "document,menu=export" -\Format text txt "Plain text" a "" "%%" "document,menu=export" -\Format text2 txt "Plain text (pstotext)" "" "" "%%" "document" -\Format text3 txt "Plain text (ps2ascii)" "" "" "%%" "document" -\Format text4 txt "Plain text (catdvi)" "" "" "%%" "document" -\Format textparagraph txt "Plain Text, Join Lines" "" "" "%%" "document"''' ]) + rc_entry = [r'''\Format asciichess asc "Plain text (chess output)" "" "" "%%" "" "" +\Format asciiimage asc "Plain text (image)" "" "" "%%" "" "" +\Format asciixfig asc "Plain text (Xfig output)" "" "" "%%" "" "" +\Format dateout tmp "date (output)" "" "" "%%" "" "" +\Format docbook sgml DocBook B "" "%%" "document,menu=export" "" +\Format docbook-xml xml "DocBook (XML)" "" "" "%%" "document,menu=export" "application/docbook+xml" +\Format dot dot "Graphviz Dot" "" "" "%%" "vector" "text/vnd.graphviz" +\Format dviluatex tex "LaTeX (dviluatex)" "" "" "%%" "document,menu=export" "" +\Format platex tex "LaTeX (pLaTeX)" "" "" "%%" "document,menu=export" "" +\Format literate nw NoWeb N "" "%%" "document,menu=export" "" +\Format sweave Rnw "Sweave" S "" "%%" "document,menu=export" "" +\Format r R "R/S code" "" "" "%%" "document,menu=export" "" +\Format knitr Rnw "Rnw (knitr)" "" "" "%%" "document,menu=export" "" +\Format lilypond ly "LilyPond music" "" "" "%%" "vector" "text/x-lilypond" +\Format lilypond-book lytex "LilyPond book (LaTeX)" "" "" "%%" "document,menu=export" "" +\Format latex tex "LaTeX (plain)" L "" "%%" "document,menu=export" "text/x-tex" +\Format luatex tex "LaTeX (LuaTeX)" "" "" "%%" "document,menu=export" "" +\Format pdflatex tex "LaTeX (pdflatex)" "" "" "%%" "document,menu=export" "" +\Format xetex tex "LaTeX (XeTeX)" "" "" "%%" "document,menu=export" "" +\Format text txt "Plain text" a "" "%%" "document,menu=export" "text/plain" +\Format text2 txt "Plain text (pstotext)" "" "" "%%" "document" "" +\Format text3 txt "Plain text (ps2ascii)" "" "" "%%" "document" "" +\Format text4 txt "Plain text (catdvi)" "" "" "%%" "document" "" +\Format textparagraph txt "Plain Text, Join Lines" "" "" "%%" "document" ""''' ]) #Spreadsheets using ssconvert from gnumeric checkViewer('gnumeric spreadsheet software', ['gnumeric'], - rc_entry = [r'''\Format gnumeric gnumeric "Gnumeric spreadsheet" "" "" "%%" "document" -\Format excel xls "Excel spreadsheet" "" "" "%%" "document" -\Format oocalc ods "OpenOffice spreadsheet" "" "" "%%" "document"''']) + rc_entry = [r'''\Format gnumeric gnumeric "Gnumeric spreadsheet" "" "" "%%" "document" "application/x-gnumeric" +\Format excel xls "Excel spreadsheet" "" "" "%%" "document" "application/vnd.ms-excel" +\Format oocalc ods "OpenOffice spreadsheet" "" "" "%%" "document" "application/vnd.oasis.opendocument.spreadsheet"''']) # checkViewer('an HTML previewer', ['firefox', 'mozilla file://$$p$$i', 'netscape'], - rc_entry = [r'\Format xhtml xhtml "LyXHTML" y "%%" "" "document,menu=export"']) + rc_entry = [r'\Format xhtml xhtml "LyXHTML" y "%%" "" "document,menu=export" "application/xhtml+xml"']) # checkEditor('a BibTeX editor', ['jabref', 'JabRef', \ 'pybliographic', 'bibdesk', 'gbib', 'kbib', \ 'kbibtex', 'sixpack', 'bibedit', 'tkbibtex' \ 'xemacs', 'gvim', 'kedit', 'kwrite', 'kate', \ 'nedit', 'gedit', 'notepad'], - rc_entry = [r'''\Format bibtex bib "BibTeX" "" "" "%%" ""''' ]) + rc_entry = [r'''\Format bibtex bib "BibTeX" "" "" "%%" "" "text/x-bibtex"''' ]) # #checkProg('a Postscript interpreter', ['gs'], # rc_entry = [ r'\ps_command "%%"' ]) checkViewer('a Postscript previewer', ['kghostview', 'okular', 'evince', 'gv', 'ghostview -swap'], - rc_entry = [r'''\Format eps eps EPS "" "%%" "" "vector" -\Format eps2 eps "EPS (uncropped)" "" "%%" "" "vector" -\Format ps ps Postscript t "%%" "" "document,vector,menu=export"''']) + rc_entry = [r'''\Format eps eps EPS "" "%%" "" "vector" "image/x-eps" +\Format eps2 eps "EPS (uncropped)" "" "%%" "" "vector" "" +\Format ps ps Postscript t "%%" "" "document,vector,menu=export" "application/postscript"''']) # for xdg-open issues look here: http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg151818.html checkViewer('a PDF previewer', ['kpdf', 'okular', 'evince', 'kghostview', 'xpdf', 'acrobat', 'acroread', \ 'gv', 'ghostview'], - rc_entry = [r'''\Format pdf pdf "PDF (ps2pdf)" P "%%" "" "document,vector,menu=export" -\Format pdf2 pdf "PDF (pdflatex)" F "%%" "" "document,vector,menu=export" -\Format pdf3 pdf "PDF (dvipdfm)" m "%%" "" "document,vector,menu=export" -\Format pdf4 pdf "PDF (XeTeX)" X "%%" "" "document,vector,menu=export" -\Format pdf5 pdf "PDF (LuaTeX)" u "%%" "" "document,vector,menu=export"''']) + rc_entry = [r'''\Format pdf pdf "PDF (ps2pdf)" P "%%" "" "document,vector,menu=export" "application/pdf" +\Format pdf2 pdf "PDF (pdflatex)" F "%%" "" "document,vector,menu=export" "" +\Format pdf3 pdf "PDF (dvipdfm)" m "%%" "" "document,vector,menu=export" "" +\Format pdf4 pdf "PDF (XeTeX)" X "%%" "" "document,vector,menu=export" "" +\Format pdf5 pdf "PDF (LuaTeX)" u "%%" "" "document,vector,menu=export" ""''']) # checkViewer('a DVI previewer', ['xdvi', 'kdvi', 'okular', 'yap', 'dviout -Set=!m'], - rc_entry = [r'''\Format dvi dvi DVI D "%%" "" "document,vector,menu=export" -\Format dvi3 dvi "DVI (LuaTeX)" V "%%" "" "document,vector,menu=export"''']) + rc_entry = [r'''\Format dvi dvi DVI D "%%" "" "document,vector,menu=export" "application/x-dvi" +\Format dvi3 dvi "DVI (LuaTeX)" V "%%" "" "document,vector,menu=export" ""''']) if dtl_tools: # Windows only: DraftDVI - addToRC(r'\Format dvi2 dvi DraftDVI "" "" "" "vector"') + addToRC(r'\Format dvi2 dvi DraftDVI "" "" "" "vector" ""') # checkViewer('an HTML previewer', ['firefox', 'mozilla file://$$p$$i', 'netscape'], - rc_entry = [r'\Format html "html, htm" HTML H "%%" "" "document,menu=export"']) + rc_entry = [r'\Format html "html, htm" HTML H "%%" "" "document,menu=export" "text/html"']) # checkViewerEditor('Noteedit', ['noteedit'], - rc_entry = [r'\Format noteedit not Noteedit "" "%%" "%%" "vector"']) + rc_entry = [r'\Format noteedit not Noteedit "" "%%" "%%" "vector" ""']) # checkViewerEditor('an OpenDocument/OpenOffice viewer', ['libreoffice', 'lwriter', 'swriter', 'oowriter', 'abiword'], - rc_entry = [r'''\Format odt odt OpenDocument "" "%%" "%%" "document,vector,menu=export" -\Format sxw sxw "OpenOffice.Org (sxw)" "" "" "" "document,vector"''']) + rc_entry = [r'''\Format odt odt OpenDocument "" "%%" "%%" "document,vector,menu=export" "application/vnd.oasis.opendocument.text" +\Format sxw sxw "OpenOffice.Org (sxw)" "" "" "" "document,vector" "application/vnd.sun.xml.writer"''']) # checkViewerEditor('a Rich Text and Word viewer', ['libreoffice', 'lwriter', 'swriter', 'oowriter', 'abiword'], - rc_entry = [r'''\Format rtf rtf "Rich Text Format" "" "%%" "%%" "document,vector,menu=export" -\Format word doc "MS Word" W "%%" "%%" "document,vector,menu=export"''']) + rc_entry = [r'''\Format rtf rtf "Rich Text Format" "" "%%" "%%" "document,vector,menu=export" "application/rtf" +\Format word doc "MS Word" W "%%" "%%" "document,vector,menu=export" "application/msword"''']) # # entries that do not need checkProg - addToRC(r'''\Format date "" "date command" "" "" "" "" -\Format csv csv "Table (CSV)" "" "" "" "document" -\Format fax "" Fax "" "" "" "document" -\Format lyx lyx LyX "" "" "" "" -\Format lyx13x 13.lyx "LyX 1.3.x" "" "" "" "document" -\Format lyx14x 14.lyx "LyX 1.4.x" "" "" "" "document" -\Format lyx15x 15.lyx "LyX 1.5.x" "" "" "" "document" -\Format lyx16x 16.lyx "LyX 1.6.x" "" "" "" "document,menu=export" -\Format lyx20x 20.lyx "LyX 2.0.x" "" "" "" "document,menu=export" -\Format clyx cjklyx "CJK LyX 1.4.x (big5)" "" "" "" "document" -\Format jlyx cjklyx "CJK LyX 1.4.x (euc-jp)" "" "" "" "document" -\Format klyx cjklyx "CJK LyX 1.4.x (euc-kr)" "" "" "" "document" -\Format lyxpreview lyxpreview "LyX Preview" "" "" "" "" -\Format pdftex pdftex_t PDFTEX "" "" "" "" -\Format program "" Program "" "" "" "" -\Format pstex pstex_t PSTEX "" "" "" "" -\Format wmf wmf "Windows Metafile" "" "" "" "vector" -\Format emf emf "Enhanced Metafile" "" "" "" "vector" -\Format wordhtml "html, htm" "HTML (MS Word)" "" "" "" "document" + addToRC(r'''\Format date "" "date command" "" "" "" "" "" +\Format csv csv "Table (CSV)" "" "" "" "document" "text/csv" +\Format fax "" Fax "" "" "" "document" "" +\Format lyx lyx LyX "" "" "" "" "application/x-lyx" +\Format lyx13x 13.lyx "LyX 1.3.x" "" "" "" "document" "" +\Format lyx14x 14.lyx "LyX 1.4.x" "" "" "" "document" "" +\Format lyx15x 15.lyx "LyX 1.5.x" "" "" "" "document" "" +\Format lyx16x 16.lyx "LyX 1.6.x" "" "" "" "document,menu=export" "" +\Format lyx20x 20.lyx "LyX 2.0.x" "" "" "" "document,menu=export" "" +\Format clyx cjklyx "CJK LyX 1.4.x (big5)" "" "" "" "document" "" +\Format jlyx cjklyx "CJK LyX 1.4.x (euc-jp)" "" "" "" "document" "" +\Format klyx cjklyx "CJK LyX 1.4.x (euc-kr)" "" "" "" "document" "" +\Format lyxpreview lyxpreview "LyX Preview" "" "" "" "" "" +\Format pdftex pdftex_t PDFTEX "" "" "" "" "" +\Format program "" Program "" "" "" "" "" +\Format pstex pstex_t PSTEX "" "" "" "" "" +\Format wmf wmf "Windows Metafile" "" "" "" "vector" "image/x-wmf" +\Format emf emf "Enhanced Metafile" "" "" "" "vector" "image/x-emf" +\Format wordhtml "html, htm" "HTML (MS Word)" "" "" "" "document" "" ''') @@ -903,10 +903,10 @@ def checkConverterEntries(): # So, we configure the appropriate version according to the platform. cmd = r'\converter lyx %s "python -tt $$s/scripts/lyxpak.py $$r/$$f" ""' if os.name == 'nt': - addToRC(r'\Format lyxzip zip "LyX Archive (zip)" "" "" "" "document,menu=export"') + addToRC(r'\Format lyxzip zip "LyX Archive (zip)" "" "" "" "document,menu=export" ""') addToRC(cmd % "lyxzip") else: - addToRC(r'\Format lyxgz gz "LyX Archive (tar.gz)" "" "" "" "document,menu=export"') + addToRC(r'\Format lyxgz gz "LyX Archive (tar.gz)" "" "" "" "document,menu=export" ""') addToRC(cmd % "lyxgz") # @@ -1315,7 +1315,7 @@ def removeTempFiles(): if __name__ == '__main__': lyx_check_config = True outfile = 'lyxrc.defaults' - lyxrc_fileformat = 3 + lyxrc_fileformat = 7 rc_entries = '' lyx_keep_temps = False version_suffix = '' diff --git a/lib/doc/Customization.lyx b/lib/doc/Customization.lyx index 6541c80c23..c3024dfe09 100644 --- a/lib/doc/Customization.lyx +++ b/lib/doc/Customization.lyx @@ -126,11 +126,12 @@ End \papercolumns 1 \papersides 2 \paperpagestyle headings -\tracking_changes false +\tracking_changes true \output_changes false \html_math_output 0 \html_css_as_file 0 \html_be_strict true +\author -195340706 "Georg Baum" \end_header \begin_body @@ -1461,6 +1462,43 @@ Edit externally in the appearing context menu. \end_layout +\begin_layout Standard + +\change_inserted -195340706 1329851811 +The +\begin_inset Flex MenuItem +status collapsed + +\begin_layout Plain Layout +MIME +\end_layout + +\end_inset + + type of a format is optional, but if it is specified, it must be unique + across all formats. + It is used to detect files of this format from the file contents. + For some important file formats there is no MIME type officially registered + with the +\begin_inset CommandInset href +LatexCommand href +name "IANA" +target "http://www.iana.org/assignments/media-types/" + +\end_inset + +. + Therefore LyX uses the extended list of MIME types as specified by +\begin_inset CommandInset href +LatexCommand href +name "freedesktop.org" +target "http://www.freedesktop.org/wiki/Specifications/shared-mime-info-spec" + +\end_inset + +. +\end_layout + \begin_layout Standard The \begin_inset Flex MenuItem diff --git a/lib/scripts/prefs2prefs_prefs.py b/lib/scripts/prefs2prefs_prefs.py index a7216e03bd..a5e9e340b9 100644 --- a/lib/scripts/prefs2prefs_prefs.py +++ b/lib/scripts/prefs2prefs_prefs.py @@ -36,13 +36,41 @@ # Add use_qimage option. # No conversion necessary. -import re +# Incremented to format 7, r40789 by gb +# Add mime type to file format +import re ########################################################### # # Conversion chain +def get_format(line): + entries = [] + i = 0 + while i < len(line): + if line[i] == '"': + beg = i + 1 + i = i + 1 + while i < len(line) and line[i] != '"': + if line[i] == '\\' and i < len(line) - 1 and line[i+1] == '"': + # convert \" to " + i = i + 1 + i = i + 1 + end = i + entries.append(line[beg:end].replace('\\"', '"')) + elif line[i] == '#': + return entries + elif not line[i].isspace(): + beg = i + while not line[i].isspace(): + i = i + 1 + end = i + entries.append(line[beg:end]) + i = i + 1 + return entries + + def simple_renaming(line, old, new): i = line.lower().find(old.lower()) if i == -1: @@ -135,6 +163,59 @@ def remove_default_papersize(line): return no_match return (True, "") +def add_mime_types(line): + if not line.lower().startswith("\\format"): + return no_match + entries = get_format(line) + converted = line + i = len(entries) + while i < 7: + converted = converted + ' ""' + i = i + 1 + formats = {'tgif':'application/x-tgif', \ + 'fig':'application/x-xfig', \ + 'dia':'application/x-dia-diagram', \ + 'odg':'application/vnd.oasis.opendocument.graphics', \ + 'svg':'image/svg+xml', \ + 'bmp':'image/x-bmp', \ + 'gif':'image/gif', \ + 'jpg':'image/jpeg', \ + 'pbm':'image/x-portable-bitmap', \ + 'pgm':'image/x-portable-graymap', \ + 'png':'image/x-png', \ + 'ppm':'image/x-portable-pixmap', \ + 'tiff':'image/tiff', \ + 'xbm':'image/x-xbitmap', \ + 'xpm':'image/x-xpixmap', \ + 'docbook-xml':'application/docbook+xml', \ + 'dot':'text/vnd.graphviz', \ + 'ly':'text/x-lilypond', \ + 'latex':'text/x-tex', \ + 'text':'text/plain', \ + 'gnumeric':'application/x-gnumeric', \ + 'excel':'application/vnd.ms-excel', \ + 'oocalc':'application/vnd.oasis.opendocument.spreadsheet', \ + 'xhtml':'application/xhtml+xml', \ + 'bib':'text/x-bibtex', \ + 'eps':'image/x-eps', \ + 'ps':'application/postscript', \ + 'pdf':'application/pdf', \ + 'dvi':'application/x-dvi', \ + 'html':'text/html', \ + 'odt':'application/vnd.oasis.opendocument.text', \ + 'sxw':'application/vnd.sun.xml.writer', \ + 'rtf':'application/rtf', \ + 'doc':'application/msword', \ + 'csv':'text/csv', \ + 'lyx':'application/x-lyx', \ + 'wmf':'image/x-wmf', \ + 'emf':'image/x-emf'} + if entries[1] in formats.keys(): + converted = converted + ' "' + formats[entries[1]] + '"' + else: + converted = converted + ' ""' + return (True, converted) + ######################## @@ -152,4 +233,5 @@ conversions = [ [ 4, [ remove_default_papersize ]], [ 5, []], [ 6, []], + [ 7, [add_mime_types]], ] diff --git a/src/Buffer.cpp b/src/Buffer.cpp index 766cbfe291..a53df7b752 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -1002,7 +1002,7 @@ Buffer::ReadStatus Buffer::readFile(FileName const & fn) d->file_fully_loaded = true; d->read_only = !d->filename.isWritable(); - params().compressed = d->filename.isZippedFile(); + params().compressed = formats.isZippedFile(d->filename); saveCheckSum(); return ReadSuccess; } diff --git a/src/Format.cpp b/src/Format.cpp index 1ae3960163..4e2f07ba48 100644 --- a/src/Format.cpp +++ b/src/Format.cpp @@ -37,6 +37,10 @@ #include "support/linkback/LinkBackProxy.h" #endif +#ifdef HAVE_MAGIC_H +#include +#endif + using namespace std; using namespace lyx::support; @@ -78,6 +82,21 @@ private: }; +class FormatMimeEqual : public unary_function { +public: + FormatMimeEqual(string const & mime) + : mime_(mime) {} + bool operator()(Format const & f) const + { + // The test for empty mime strings is needed since we allow + // formats with empty mime types. + return f.mime() == mime_ && !mime_.empty(); + } +private: + string mime_; +}; + + class FormatPrettyNameEqual : public unary_function { public: FormatPrettyNameEqual(string const & prettyname) @@ -101,9 +120,9 @@ bool operator<(Format const & a, Format const & b) Format::Format(string const & n, string const & e, string const & p, string const & s, string const & v, string const & ed, - int flags) + string const & m, int flags) : name_(n), prettyname_(p), shortcut_(s), viewer_(v), - editor_(ed), flags_(flags) + editor_(ed), mime_(m), flags_(flags) { extension_list_ = getVectorFromString(e, ","); LYXERR(Debug::GRAPHICS, "New Format: n=" << n << ", flags=" << flags); @@ -168,10 +187,39 @@ string Formats::getFormatFromFile(FileName const & filename) const if (filename.empty()) return string(); +#ifdef HAVE_MAGIC_H + magic_t magic_cookie = magic_open(MAGIC_MIME); + if (magic_cookie) { + string format; + if (magic_load(magic_cookie, NULL) != 0) { + LYXERR(Debug::GRAPHICS, "Formats::getFormatFromFile\n" + << "\tCouldn't load magic database - " + << magic_error(magic_cookie)); + } else { + string mime = magic_file(magic_cookie, + filename.toFilesystemEncoding().c_str()); + mime = token(mime, ';', 0); + // we need our own ps/eps detection + if (mime != "application/postscript") { + Formats::const_iterator cit = + find_if(formatlist.begin(), formatlist.end(), + FormatMimeEqual(mime)); + if (cit != formats.end()) { + LYXERR(Debug::GRAPHICS, "\tgot format from MIME type: " + << mime << " -> " << cit->name()); + format = cit->name(); + } + } + } + magic_close(magic_cookie); + if (!format.empty()) + return format; + } +#endif + string const format = filename.guessFormatFromContents(); string const ext = getExtension(filename.absFileName()); - if ((format == "gzip" || format == "zip" || format == "compress") - && !ext.empty()) { + if (isZippedFileFormat(format) && !ext.empty()) { string const & fmt_name = formats.getFormatFromExtension(ext); if (!fmt_name.empty()) { Format const * p_format = formats.getFormat(fmt_name); @@ -244,6 +292,17 @@ bool Formats::isZippedFile(support::FileName const & filename) const { } +bool Formats::isZippedFileFormat(string const & format) +{ + return contains("gzip zip compress", format) && !format.empty(); +} + + +bool Formats::isPostScriptFileFormat(string const & format) +{ + return format == "ps" || format == "eps"; +} + static string fixCommand(string const & cmd, string const & ext, os::auto_open_mode mode) { @@ -291,24 +350,24 @@ void Formats::add(string const & name) { if (!getFormat(name)) add(name, name, name, string(), string(), string(), - Format::document); + string(), Format::document); } void Formats::add(string const & name, string const & extensions, string const & prettyname, string const & shortcut, string const & viewer, string const & editor, - int flags) + string const & mime, int flags) { FormatList::iterator it = find_if(formatlist.begin(), formatlist.end(), FormatNamesEqual(name)); if (it == formatlist.end()) formatlist.push_back(Format(name, extensions, prettyname, - shortcut, viewer, editor, flags)); + shortcut, viewer, editor, mime, flags)); else *it = Format(name, extensions, prettyname, shortcut, viewer, - editor, flags); + editor, mime, flags); } diff --git a/src/Format.h b/src/Format.h index 12e14f9e15..9d91ae1442 100644 --- a/src/Format.h +++ b/src/Format.h @@ -43,7 +43,7 @@ public: /// Format(std::string const & n, std::string const & e, std::string const & p, std::string const & s, std::string const & v, std::string const & ed, - int); + std::string const & m, int); /// bool dummy() const; /// Is \p ext a valid filename extension for this format? @@ -83,6 +83,10 @@ public: /// void setEditor(std::string const & v) { editor_ = v; } /// + std::string const & mime() const { return mime_; } + /// + void setMime(std::string const & m) { mime_ = m; } + /// bool documentFormat() const { return flags_ & document; } /// bool vectorFormat() const { return flags_ & vector; } @@ -111,6 +115,14 @@ private: std::string viewer_; /// Editor for this format. \sa viewer_. std::string editor_; + /*! + * Full MIME type, e.g. "text/x-tex". + * Only types listed by the shared MIME database of freedesktop.org + * should be added. + * This field may be empty, but it must be unique across all formats + * if it is set. + */ + std::string mime_; /// int flags_; }; @@ -148,6 +160,10 @@ public: ** @note For natively zipped formats, such as dia/odg, this returns false. **/ bool isZippedFile(support::FileName const & filename) const; + /// check for zipped file format + static bool isZippedFileFormat(std::string const & format); + /// check for PostScript file format + static bool isPostScriptFileFormat(std::string const & format); /// Set editor and/or viewer to "auto" for formats that can be /// opened by the OS. void setAutoOpen(); @@ -159,7 +175,7 @@ public: void add(std::string const & name, std::string const & extensions, std::string const & prettyname, std::string const & shortcut, std::string const & viewer, std::string const & editor, - int flags); + std::string const & mime, int flags); /// void erase(std::string const & name); /// diff --git a/src/Lexer.cpp b/src/Lexer.cpp index 664e1b9bfb..06a3408f41 100644 --- a/src/Lexer.cpp +++ b/src/Lexer.cpp @@ -14,6 +14,7 @@ #include #include "Lexer.h" +#include "Format.h" #include "support/convert.h" #include "support/debug.h" @@ -237,10 +238,14 @@ void Lexer::Pimpl::popTable() bool Lexer::Pimpl::setFile(FileName const & filename) { +#ifdef TEX2LYX + // tex2lyx does not read lyxrc and therefore can't really check for + // zipped formats. + if (false) { +#else // Check the format of the file. - string const format = filename.guessFormatFromContents(); - - if (format == "gzip" || format == "zip" || format == "compress") { + if (formats.isZippedFile(filename)) { +#endif LYXERR(Debug::LYXLEX, "lyxlex: compressed"); // The check only outputs a debug message, because it triggers // a bug in compaq cxx 6.2, where is_open() returns 'true' for diff --git a/src/LyXRC.cpp b/src/LyXRC.cpp index fa86a02fd1..a07c8e6d80 100644 --- a/src/LyXRC.cpp +++ b/src/LyXRC.cpp @@ -55,7 +55,7 @@ namespace os = support::os; namespace { -static unsigned int const LYXRC_FILEFORMAT = 6; // younes: add use_qimage option +static unsigned int const LYXRC_FILEFORMAT = 7; // gb: add mime types // when adding something to this array keep it sorted! LexerKeyword lyxrcTags[] = { @@ -1085,28 +1085,29 @@ LyXRC::ReturnValues LyXRC::read(Lexer & lexrc, bool check_format) break; } case RC_FILEFORMAT: { + bool ok = true; string format, extensions, prettyname, shortcut; - lexrc >> format >> extensions >> prettyname >> shortcut; + if (!(lexrc >> format >> extensions)) + ok = false; + if (ok && lexrc.next(true)) + prettyname = lexrc.getString(); + else + ok = false; + if (ok) + if(!(lexrc >> shortcut)) + ok = false; string viewer, editor; - if (lexrc.next(true)) + if (ok && lexrc.next(true)) viewer = lexrc.getString(); - if (lexrc.next(true)) + else + ok = false; + if (ok && lexrc.next(true)) editor = lexrc.getString(); - string flags; - // Hack to ensure compatibility with versions older - // than 1.5.0 - int le = lexrc.lex(); - if (le != Lexer::LEX_FEOF && le != Lexer::LEX_UNDEF) { - flags = lexrc.getString(); - if (le != Lexer::LEX_DATA) { - // We have got a known token. - // Therefore this is an old style - // format definition without - // flags. - lexrc.pushToken(flags); - flags.erase(); - } - } + else + ok = false; + string flags, mime; + if (!(lexrc >> flags >> mime)) + ok = false; int flgs = Format::none; while (!flags.empty()) { string flag; @@ -1124,14 +1125,16 @@ LyXRC::ReturnValues LyXRC::read(Lexer & lexrc, bool check_format) << flag << "' for format `" << format << "'."); } - if (prettyname.empty()) { + if (!ok) + LYXERR0("Syntax error in format " << format); + else if (prettyname.empty()) { if (theConverters().formatIsUsed(format)) LYXERR0("Can't delete format " << format); else formats.erase(format); } else { formats.add(format, extensions, prettyname, - shortcut, viewer, editor, flgs); + shortcut, viewer, editor, mime, flgs); } break; } @@ -2711,7 +2714,8 @@ void LyXRC::write(ostream & os, bool ignore_system_lyxrc, string const & name) c format->editor() != cit->editor() || format->documentFormat() != cit->documentFormat() || format->vectorFormat() != cit->vectorFormat() || - format->inExportMenu() != cit->inExportMenu()) { + format->inExportMenu() != cit->inExportMenu() || + format->mime() != cit->mime()) { os << "\\format \"" << cit->name() << "\" \"" << cit->extensions() << "\" \"" << cit->prettyname() << "\" \"" @@ -2729,7 +2733,7 @@ void LyXRC::write(ostream & os, bool ignore_system_lyxrc, string const & name) c flags.push_back("menu=export"); os << getStringFromVector(flags); - os << "\"\n"; + os << "\" \"" << cit->mime() << "\"\n"; } } @@ -2738,7 +2742,7 @@ void LyXRC::write(ostream & os, bool ignore_system_lyxrc, string const & name) c cit != system_formats.end(); ++cit) if (!formats.getFormat(cit->name())) os << "\\format \"" << cit->name() - << "\" \"\" \"\" \"\" \"\" \"\" \"\"\n"; + << "\" \"\" \"\" \"\" \"\" \"\" \"\" \"\"\n"; if (tag != RC_LAST) break; case RC_VIEWER_ALTERNATIVES: { diff --git a/src/frontends/qt4/GuiPrefs.cpp b/src/frontends/qt4/GuiPrefs.cpp index be57f7e00e..362e289be0 100644 --- a/src/frontends/qt4/GuiPrefs.cpp +++ b/src/frontends/qt4/GuiPrefs.cpp @@ -1983,6 +1983,7 @@ void PrefFileformats::on_formatsCB_currentIndexChanged(int i) formatED->setText(toqstr(f.name())); copierED->setText(toqstr(form_->movers().command(f.name()))); extensionsED->setText(toqstr(f.extensions())); + mimeED->setText(toqstr(f.mime())); shortcutED->setText( toqstr(l10n_shortcut(f.prettyname(), f.shortcut()))); documentCB->setChecked((f.documentFormat())); @@ -2038,6 +2039,13 @@ void PrefFileformats::on_editorED_textEdited(const QString & s) } +void PrefFileformats::on_mimeED_textEdited(const QString & s) +{ + currentFormat().setMime(fromqstr(s)); + changed(); +} + + void PrefFileformats::on_shortcutED_textEdited(const QString & s) { string const new_shortcut = fromqstr(s); @@ -2195,7 +2203,7 @@ Format & PrefFileformats::currentFormat() void PrefFileformats::on_formatNewPB_clicked() { - form_->formats().add("", "", "", "", "", "", Format::none); + form_->formats().add("", "", "", "", "", "", "", Format::none); updateView(); formatsCB->setCurrentIndex(0); formatsCB->setFocus(Qt::OtherFocusReason); diff --git a/src/frontends/qt4/GuiPrefs.h b/src/frontends/qt4/GuiPrefs.h index c1b8ec286d..8d9028042d 100644 --- a/src/frontends/qt4/GuiPrefs.h +++ b/src/frontends/qt4/GuiPrefs.h @@ -358,6 +358,7 @@ private Q_SLOTS: void on_extensionsED_textEdited(const QString &); void on_viewerED_textEdited(const QString &); void on_editorED_textEdited(const QString &); + void on_mimeED_textEdited(const QString &); void on_shortcutED_textEdited(const QString &); void on_formatED_editingFinished(); void on_formatED_textChanged(const QString &); diff --git a/src/frontends/qt4/ui/PrefFileformatsUi.ui b/src/frontends/qt4/ui/PrefFileformatsUi.ui index 923ccdd6a6..cfbad46b31 100644 --- a/src/frontends/qt4/ui/PrefFileformatsUi.ui +++ b/src/frontends/qt4/ui/PrefFileformatsUi.ui @@ -103,6 +103,19 @@ + + + + &MIME: + + + mimeED + + + + + + @@ -239,6 +252,7 @@ editorED viewerCO viewerED + mimeED copierED diff --git a/src/graphics/epstools.cpp b/src/graphics/epstools.cpp index 44d577c14f..5fb403c3ec 100644 --- a/src/graphics/epstools.cpp +++ b/src/graphics/epstools.cpp @@ -46,11 +46,11 @@ string const readBB_from_PSFile(FileName const & file) // end of the file. Than we have in the header: // %%BoundingBox: (atend) // In this case we must check the end. - bool zipped = file.isZippedFile(); + bool const zipped = formats.isZippedFile(file); FileName const file_ = zipped ? unzipFile(file) : file; - string const format = file_.guessFormatFromContents(); + string const format = formats.getFormatFromFile(file_); - if (format != "eps" && format != "ps") { + if (!Formats::isPostScriptFileFormat(format)) { LYXERR(Debug::GRAPHICS, "[readBB_from_PSFile] no(e)ps-format"); if (zipped) file_.removeFile(); diff --git a/src/support/FileName.cpp b/src/support/FileName.cpp index 4daa364736..2d4d8ef0df 100644 --- a/src/support/FileName.cpp +++ b/src/support/FileName.cpp @@ -948,13 +948,6 @@ string FileName::guessFormatFromContents() const } -bool FileName::isZippedFile() const -{ - string const type = guessFormatFromContents(); - return contains("gzip zip compress", type) && !type.empty(); -} - - docstring const FileName::relPath(string const & path) const { // FIXME UNICODE diff --git a/src/support/FileName.h b/src/support/FileName.h index da1f75fbee..f8da6b596d 100644 --- a/src/support/FileName.h +++ b/src/support/FileName.h @@ -175,9 +175,6 @@ public: */ std::string guessFormatFromContents() const; - /// check for zipped file - bool isZippedFile() const; - static FileName fromFilesystemEncoding(std::string const & name); /// (securely) create a temporary file with the given mask. /// \p mask must be in filesystem encoding, if it contains a