summaryrefslogtreecommitdiffstats
path: root/kcontrol/kfontinst
diff options
context:
space:
mode:
Diffstat (limited to 'kcontrol/kfontinst')
-rw-r--r--kcontrol/kfontinst/AUTHORS1
-rw-r--r--kcontrol/kfontinst/ChangeLog490
-rw-r--r--kcontrol/kfontinst/Makefile.am14
-rw-r--r--kcontrol/kfontinst/TODO1
-rw-r--r--kcontrol/kfontinst/configure.in.bot12
-rw-r--r--kcontrol/kfontinst/configure.in.in155
-rw-r--r--kcontrol/kfontinst/installfont.desktop79
-rw-r--r--kcontrol/kfontinst/kcmfontinst/KCmFontInst.cpp647
-rw-r--r--kcontrol/kfontinst/kcmfontinst/KCmFontInst.h116
-rw-r--r--kcontrol/kfontinst/kcmfontinst/KFileFontIconView.cpp88
-rw-r--r--kcontrol/kfontinst/kcmfontinst/KFileFontIconView.h55
-rw-r--r--kcontrol/kfontinst/kcmfontinst/KFileFontView.cpp645
-rw-r--r--kcontrol/kfontinst/kcmfontinst/KFileFontView.h219
-rw-r--r--kcontrol/kfontinst/kcmfontinst/Makefile.am31
-rw-r--r--kcontrol/kfontinst/kcmfontinst/PrintDialog.cpp74
-rw-r--r--kcontrol/kfontinst/kcmfontinst/PrintDialog.h56
-rw-r--r--kcontrol/kfontinst/kcmfontinst/SettingsDialog.cpp99
-rw-r--r--kcontrol/kfontinst/kcmfontinst/SettingsDialog.h57
-rw-r--r--kcontrol/kfontinst/kcmfontinst/cr16-action-newfont.pngbin0 -> 613 bytes
-rw-r--r--kcontrol/kfontinst/kcmfontinst/cr22-action-newfont.pngbin0 -> 951 bytes
-rw-r--r--kcontrol/kfontinst/kcmfontinst/cr32-action-newfont.pngbin0 -> 1821 bytes
-rw-r--r--kcontrol/kfontinst/kcmfontinst/kcmfontinst.desktop235
-rw-r--r--kcontrol/kfontinst/kfile-plugin/KFileFont.cpp422
-rw-r--r--kcontrol/kfontinst/kfile-plugin/KFileFont.h58
-rw-r--r--kcontrol/kfontinst/kfile-plugin/Makefile.am13
-rw-r--r--kcontrol/kfontinst/kfile-plugin/kfile_font.desktop86
-rw-r--r--kcontrol/kfontinst/kfontinst/FontEngine.cpp376
-rw-r--r--kcontrol/kfontinst/kfontinst/FontEngine.h142
-rw-r--r--kcontrol/kfontinst/kfontinst/Fontmap.cpp596
-rw-r--r--kcontrol/kfontinst/kfontinst/Fontmap.h79
-rw-r--r--kcontrol/kfontinst/kfontinst/GetPid.c519
-rw-r--r--kcontrol/kfontinst/kfontinst/Main.cpp335
-rw-r--r--kcontrol/kfontinst/kfontinst/Makefile.am16
-rw-r--r--kcontrol/kfontinst/kfontinst/XConfig.cpp760
-rw-r--r--kcontrol/kfontinst/kfontinst/XConfig.h114
-rw-r--r--kcontrol/kfontinst/kio/KioFonts.cpp2534
-rw-r--r--kcontrol/kfontinst/kio/KioFonts.h161
-rw-r--r--kcontrol/kfontinst/kio/Makefile.am20
-rw-r--r--kcontrol/kfontinst/kio/folder.desktop80
-rw-r--r--kcontrol/kfontinst/kio/fonts.desktop85
-rw-r--r--kcontrol/kfontinst/kio/fonts.protocol18
-rw-r--r--kcontrol/kfontinst/kio/package.desktop74
-rw-r--r--kcontrol/kfontinst/kio/system-folder.desktop79
-rw-r--r--kcontrol/kfontinst/lib/FcEngine.cpp1179
-rw-r--r--kcontrol/kfontinst/lib/FcEngine.h118
-rw-r--r--kcontrol/kfontinst/lib/KfiConstants.h73
-rw-r--r--kcontrol/kfontinst/lib/Makefile.am14
-rw-r--r--kcontrol/kfontinst/lib/Misc.cpp238
-rw-r--r--kcontrol/kfontinst/lib/Misc.h76
-rw-r--r--kcontrol/kfontinst/thumbnail/FontThumbnail.cpp73
-rw-r--r--kcontrol/kfontinst/thumbnail/FontThumbnail.h55
-rw-r--r--kcontrol/kfontinst/thumbnail/Makefile.am14
-rw-r--r--kcontrol/kfontinst/thumbnail/fontthumbnail.desktop85
-rw-r--r--kcontrol/kfontinst/viewpart/FontPreview.cpp118
-rw-r--r--kcontrol/kfontinst/viewpart/FontPreview.h83
-rw-r--r--kcontrol/kfontinst/viewpart/FontViewPart.cpp282
-rw-r--r--kcontrol/kfontinst/viewpart/FontViewPart.h85
-rw-r--r--kcontrol/kfontinst/viewpart/FontViewPartFactory.cpp86
-rw-r--r--kcontrol/kfontinst/viewpart/FontViewPartFactory.h60
-rw-r--r--kcontrol/kfontinst/viewpart/FontViewerApp.cpp130
-rw-r--r--kcontrol/kfontinst/viewpart/FontViewerApp.h68
-rw-r--r--kcontrol/kfontinst/viewpart/KfiPrint.cpp193
-rw-r--r--kcontrol/kfontinst/viewpart/KfiPrint.h49
-rw-r--r--kcontrol/kfontinst/viewpart/Makefile.am30
-rw-r--r--kcontrol/kfontinst/viewpart/kfontview.desktop100
-rw-r--r--kcontrol/kfontinst/viewpart/kfontviewpart.desktop86
-rw-r--r--kcontrol/kfontinst/viewpart/kfontviewpart.rc9
-rw-r--r--kcontrol/kfontinst/viewpart/kfontviewui.rc4
68 files changed, 12949 insertions, 0 deletions
diff --git a/kcontrol/kfontinst/AUTHORS b/kcontrol/kfontinst/AUTHORS
new file mode 100644
index 000000000..afabc4a80
--- /dev/null
+++ b/kcontrol/kfontinst/AUTHORS
@@ -0,0 +1 @@
+Craig Drummond <craig@kde.org>
diff --git a/kcontrol/kfontinst/ChangeLog b/kcontrol/kfontinst/ChangeLog
new file mode 100644
index 000000000..b00a53f1e
--- /dev/null
+++ b/kcontrol/kfontinst/ChangeLog
@@ -0,0 +1,490 @@
+KDE3.4 -> KDE3.5
+================
+1. When copying a file out of fonts sub-system, copy as filename, or <fontname>.fonts.tar.gz
+ in the case of multiple font files mapped to the same font name.
+
+ e.g. Times New Roman -> times.ttf
+ Helvetica, Bold Oblique-> Hevetica, Bold Oblique.fonts.tar.gz
+ Which contains:
+ 75dpi_helvBO10.pcf.gz
+ 75dpi_helvBO12.pcf.gz
+ 100dpi_helvBO10.pcf.gz
+ 100dpi_helvBO12.pcf.gz
+ ...etc
+
+2. New mimetype: fonts/package - to cater for the above.
+3. Add settings to enable/disable configuring fonts for legacy X, and Ghostscript
+ (X defaults to true, and Ghostscript defaults to false)
+4. Show mime-type in detailed view.
+5. Simple font sample printing - but only of installed fonts!
+6. Add toggle button to control display of bitmap fonts.
+
+KDE3.3 -> KDE3.4
+================
+1. Font listing comes from fontconfig. This means that fonts will be grouped, i.e.
+ previously each size of a bitmap font was shown seperately, now only 1 font
+ will be displayed which represents all sizes.
+2. Only fonts, and not folders (except System and Personal), are now shown.
+3. Creation of afms from pfa/pfb and a pfm file.
+4. Previews are drawn via Xft - previously FreeType was called directly.
+5. New font preview look.
+6. No longer dependant upon file extension.
+7. Check for FPE of "fontconfig" -> if set, then no need to configure X core fonts.
+
+KDE3.2 -> KDE3.3
+================
+1. List fonts as "Full Name" -> i.e. "Times New Roman".
+2. Preview of bitmap fonts.
+3. No fontname-title in thumbnails - as fonts:/ lists the fontnames!
+4. When copying to fonts:/ (as non-root) only ask for destination if more than 5 seconds
+ since previously asked.
+5. Add a konqueror service menu "Install"
+6. Use FreeType2 for reading Type1 - instead of parsing the pfa/pfb header.
+7. FamilyName is now the fonts *real* family name - no adding of style information.
+8. Add extra style information (which was previously added to FamilyName) into the XLFD.
+9. Consider regular weight to be medium (same as mkfontscale).
+10. Default to width=normal, weight=medium if not set.
+11. Allow change of preview string.
+12. Allow zooming in/out of preview.
+13. Waterfall font preview.
+14. Use font preview part in the KControl module - less code duplication.
+15. Include simple fontviwer app - basically just an application wrapper for the viewpart.
+
+KDE3.1 -> KDE3.2
+================
+1. Re-designed (yet again...) to be a kio slave. As a user, starting fonts:/ will display
+
+ Personal Lists contents of $HOME/.fonts and $KDEHOME/share/fonts (where previous installer installed to)
+ Fonts are installed to $HOME/.fonts
+
+ System Lists contents of /usr/local/share/fonts, /usr/share/fonts, and /usr/X11R6/lib/X11/fonts
+ Fonts are installed to /usr/local/share/fonts (as per FHS)
+
+ To install fonts system wide, just drop onto "System" and root's password will be asked
+ for.
+
+ As root, fonts:/ will show the same as fonts:/System (but without the System part...)
+
+2. New kcontrol module that uses fonts:/
+3. Removed:
+ AFM creation -- only really required (TTF wise) for SO <6.0
+ StarOffice configuration (S0 6.0 / OO.o is *much* better anyway)
+4. X font server (xfs) - if used - is refreshed by seding a SIGUSR1 instead of
+ relying on a /etc/init.d/xfs script. This is much more portable.
+5. Simple FontView part for konqueror - this is basically a big re-sizable preview of the font.
+6. Speed up creation of fonts.dir and fonts.scale - by reading in any existing files, and using the
+ entries from these instead of loading and testing the font (if listed).
+7. Better font preview and thumbnails.
+8. Only add a dir to fontpath if fonts.dir has greater than 0 entries!
+9. Use /etc/fonts/local.conf as root fontconfig file.
+10. Only add dirs to fontconfig if *not* a sub-dir of an existing dir.
+11. Ensure that top-level fonts dir is always in fontpath.
+12. A Fontmap file is created in each sub dir, which is then combined into 1 top level Fontmap file.
+ ~/.fonts/Fontmap for normal users, and /etc/fonts/Fontmap for root.
+13. Modify <ghostscript dir><sub-dir>/Fontmap to contain:
+ (/etc/fonts/Fontmap) .runlibfile
+ ...as this is the system-wide Fontmap file created. As for the per-user, one, hmmm...
+14. When a folder is configured, ensure fonts.dir/fonts.scale/Fontmap/.fonts-config-timestamp (SuSE
+ specific) all have the same timestamp (if they exist). Helps to discover if a folder has been
+ modified - in which case it needs to be reconfigured (and should happen automatically).
+15. Add support for TrueType Collections (.ttc), and OpenType (.otf) fonts. Currently TTC's are only
+ configured for X - need to also configure GS to see other faces.
+16. CID fonts are *not* handled - therefore don't list the X11 CID directory, and don't let users
+ try to create this.
+17. Don't list "encodings" in fonts:/System - and don't allow users to create this.
+18. Use XFree86's libfontenc (if found) to read font-encodings.
+19. Handle 1bpp glyphs in thumbnail code.
+20. Ensure X fontpaths *never* end in "/" - i.e. when write XF86Config, xfs/config,
+ or fontpaths remove any trailing "/"
+21. When adding/removing an unscaled dir from X font path, ensure ":unscaled" is
+ part of the path!
+22. Call fc-cache on top-level dir, not on each dir.
+23. Use "~" in Xft config and user X config files -> e.g. /home/user/.fonts -> ~/.fonts
+24. Remove top-level dir spec from top-level fontmap, e.g.
+
+ TimesNewRomanPSMT (/home/user/.fonts/wibble/times.ttf);
+
+ ...becomes...
+
+ TimesNewRomanPSMT (wibble/times.ttf);
+
+25. Add meta-data for AFM files to KFile plugin.
+
+0.11-> KDE3.1
+=============
+1. Re-design of UI - removed "Install From" view.
+2. Created a KIO/thumbnail font preview class.
+3. Fonts are installed/uninstalled on "Apply".
+4. Settings are saved on "Apply".
+5. Settings tab simplified - some uneccesary settings removed.
+6. Removal of Anti-Alias tab - relevant settings moved to kcmfonts.
+7. Add kfile-plugin to display Meta data for fonts.
+8. Remove settings wizard.
+9. Drop use of internal version numbering - not tagging CVS anyway, so whats the point?
+10. DCOP interface.
+11. Remember size of main window when run via kcmshell.
+
+0.10->0.11 (KDE3.0)
+===================
+1. Port to KDE3/Qt3.
+2. Add support for CUPS's Fontmap.
+3. Create backups of system files.
+4. When install symbol encoding fonts, set encoding to "glyphs-fontspecific" in XftConfig.
+5. When install monospaced fonts, set spacing to mono in XftConfig.
+6. When first run (as root) - checks XFree86 config file to see if a font server is being used, if
+ so then fs/config is used as the config file, and "/etc/rc.d/init.d/xfs restart" is selected as
+ as the X refresh command.
+7. Only install fonts that are useable.
+8. Add checkbox to enable overwriting of existing AFMs.
+9. Remember open directories in advanced mode.
+10. Add support for .Z compressed Bitmap fonts.
+11. Read Type1 encodings from .afm files if listed as "array" in pfa/pfb.
+
+0.10b11->0.10
+=============
+1. Version added to KDE CVS.
+2. Modified some keyboard shortcuts to remove conflicts.
+3. Disable "Touch" and "Delete" folder if top-level X fonts dir is selected.
+
+0.10b10->0.10b11 (Test version...)
+================
+1. Removed "root"/"Modify" and "Help" buttons - this gives more space to font lists, plus when using "root"/"Modify" root's
+ config files are not being saved.
+2. "IsFixedPitch" flag in AFMs produced incorrectly - was outputing "false" for monospaced fonts!
+3. Added rounding to AFM metric scaling.
+4. When creating AFMs, check that each characters' BBox is within the main BBox - this is a quick fix for wingdings.afm,
+ which seems to be giving incorrect results.
+5. StarOffice 6 / OpenOffice only need AFM files for Type1 fonts - plus no config files need to be altered. Therefore, added the ability to
+ select which font types AFMs should be created for.
+6. Output *all* characters from a font into the AFM file.
+7. Fixed a bug with Full/Family name in Speedo fonts.
+8. For TrueType, Type1, and Speedo fonts - family name is obtained by using the fonts' FullName, remove FamilyName (read from file), remove
+ any weight, width, or italic designation, and re-add FamilyName. (This is because some fonts are named
+ <family><weight><italic><something else>, and <something else> was previously being lost).
+9. When adding encodings to lists, check that they aren't alredy inserted.
+
+0.10b9->0.10b10 (Test version...)
+===============
+1. Fixed a problem with non-enabled install button in basic mode - again, thanks to Hardy Griech for spotting this.
+
+0.10b8->0.10b9 (Test version...)
+==============
+
+*** NOTE
+*** Please remove any Kfontinst generated StarOffice psstd.fonts and Ghostscript Fontmap output before using this version
+
+1. StarOffice psstd.fonts generated output is no longer marked line-by line, instead it is marked as a section, e.g.
+
+ # kfontinst <user, if not root> /usr/X11R6/lib/X11/fonts/TrueType
+ <fonts...>
+ # kfontinst <user, if not root> /usr/X11R6/lib/X11/fonts/TrueType
+
+ ...Likewise for Ghostscript's Fontmap
+
+2. Limited generated StarOffice psstd.fonts lines to 126 characters, and lines longher than this will not be output. It appears
+ as if this is the max line len StarOffice will accept - thanks to Hardy Griech for discovering this.
+3. Fixed a bug where a static pointer was not reset to NULL when module was unloaded.
+4. When chekcing ps-fonts, I was looking for the string "%!PS-Adbobe", however the hershey fonts just has "%!FontType" - therefore
+ I've change the code to just look for "%!"
+5. For pcf fonts, look for FAMILY as well as FAMILY_NAME
+6. Construct name from xlfd for bitmap fonts where can't get seperate components
+
+0.10b7->0.10b8 (Test version...)
+==============
+
+*** NOTE
+*** Please remove any Kfontinst generated Ghostscript and/or StarOffice output before using this version
+
+1. Forgot to extract foundry from bitmap fonts - however, changed bitmap Xlfd creation, see below.
+2. Extract Xlfd from Bitmap fonts directly - not all fonts have each seperate component available. Thanks to Claudio Bandaloukas
+ for helping me discover the various bugs with Bitmap output.
+3. When displaying bitmap details, if individual entries (family, point size, etc) can't be read, then the
+ Xlfd will be displayed.
+4. Ghostscript & StarOffice include guards changed from "kfontinst" to "kfi" -- this will *require" removing of any previous output!
+5. Shortened generated TrueType foundry fields - to help with StarOffice
+
+0.10b6->0.10b7 (Test version...)
+==============
+1. Fixed a bug with string-to-width conversion for Type1 and bitmap fonts
+2. Fixed some compile bugs if no Xft.h found
+3. Remove any fonts.alias when deleting a dir
+4. When try to open Type1 or Speedo fonts, check magic numbers - for Speedo check char[0]=='D' or 'd', char[1]==num, char[2]=='.', and char[3]==num
+
+0.10b5->0.10b6 (Test version...)
+==============
+1. Fonts with "Normal" weight now installed as "Medium"
+2. Added support for "Oblique" in xlfd
+3. Check is performed to see if destination is writeable before enabling "Install" button, likewise for the "Remove" button.
+
+0.10b4->0.10b5 (Test version...)
+==============
+1. Forgot to reset the made-changes state of XftConfig when saved!
+2. Add a validator to math & edit line-edits to disallow usage of double-quotes & tabs
+3. Select correct default entries for field-name combos when adding an XftRule.
+4. Removed check for number of items in match list, as these are not always required (such as for the sub-pixel hinting
+ rule.)
+5. When setting rgba - use symbolic name - previously always setting to 0!
+6. Modified help a little
+7. Reduced Advanced mode list-view treeStepSize to 10 pixels (from default of 20), this makes it easier for browsing
+ /usr/X11R6/lib/X11/fonts/etc...
+8. Fixed bug where could not remove Xft exclude range!
+9. Fixed a bug where uninstalled items could cause duplicates in "Install from" list.
+10. Renamed the "Configure System" button to "Apply" - this should make the neccessity of the option more obvious.
+11. Fixed display of uninstall folder.
+12. Added "include" and "includeif" directives from XftConfig to editor.
+
+0.10b3->0.10b4 (Test version...)
+==============
+
+*** NOTE
+*** Please delete your existing ~/.kde/share/config/kfontinstrc -or- ~/.kde2/share/config/kfontinstrc file
+*** before using this version
+
+1. Added support for X font server config files.
+2. Show "unscaled" directories in italic.
+3. Abilty to set directories as scaled/unscaled.
+4. Modified GUI slightly so that it works beter with Liquid style.
+5. Added chack to make sure XftConfig file exists before trying to parse.
+6. Advanced editing of XftConfig.
+7. Added help on XftConfig - from Danny Tholen (obiwan@mailmij.org)
+8. Removed some memory leaks
+10. Default folders changed for non-root users. KFontinst will now (upon initial start-up) select the following:
+
+ X fonts dir: $KDEHOME/share/fonts
+ XConfig file: $KDEHOME/share/fonts/fontpaths
+ XftConfig file: $HOME/.xftconfig
+ Fontmap file: $KDEHOME/share/fonts/Fontmap
+
+ ...This should make it possible for users to install fonts without being root. However, problems may arrise when
+ configuring StarOffice - as this requires some other files to be modified, which won't be possible if SO has been installed
+ by root.
+
+ ...Also to accomplish this, some changes are needed to 'startkde' - see file README.startkde
+
+11. Because of the above, when started as non-root, KFontinst will create Type1 and TrueType sub-folders in
+ $KDEHOME/share/fonts - if they do not already exist.
+12. Moved XftConfig stuff from a sub-page of settings tab into its own tab.
+13. Added question dialog if module is unloaded before system has been configured.
+14. Added ability to "touch" a X font folder - marking it as being modified, so that a re-configure of the that folder
+ can be done in order to create AFMs, modify encoding, etc.
+
+0.10b2->0.10b3 (Test version...)
+==============
+1. When locating Ghostscript's Fontmap file, sub-directories (up to a level of 4) are searched - this allows
+ for the possiblity of users using a different version of Ghostscript.
+2. Create a fonts.scale as well as fonts.dir - just incase another program runs mkfontdir.
+3. Fixed an error when creating AFMs for some symbol-encoded fonts.
+4. Re-worded SettingsWizard "Folders/Files" tab.
+5. Added a checkbox to Ghostscript configuration.
+6. Added support for XftConfig.
+7. Added/fixed support of Type1 fonts with no FullName or FamilyName fields - such as the hershey fonts.
+8. Fixed some bugs when configuring with --enable-final.
+9. Basic html help added.
+
+0.10b1->0.10b2 (Test version...)
+==============
+1. Minor compile error (struct declared as private, but used elsewhere!)
+
+0.9.2->0.10b1 (Test version...)
+=============
+1. Almost a complete re-write,
+2. Handles Speedo, and Bitmap fonts
+3. fonts.dir & encodings.dir are now created internally - no need for ttmkfdir
+4. Re-design of GUI.
+5. Advanced mode where X11 folder structure is displayed and all font types may be installed - and a Basic
+ mode where the X11 folder structure is hidden, and only TrueType and Type1 fonts may be installed.
+6. Settings wizard.
+7. Application is now a kcontrol module.
+8. Complete X11 fonts directory structure is now managed - no need for seperate 'Managed' directory.
+9. X11.PS is no longer created, instead the StarOffice printer file (*.PS) is now modified.
+10. Ported to FreeType2.
+11. Support more encodings - encodings combos now list standard encodings as well as those read from
+ .enc(.gz) files.
+12. Internal AMF creator for Type1 and TrueType fonts - ttf2pt1 and pf2afm.ps are no longer used/supplied.
+13. Removed the 'Process AFMs' & 'Delete AFMs' options - all AFMs are created be KFontinst, therefore they
+ should be OK for StarOffice and AbiWord.
+14. If a writable XF86Config file is found - then complete folders may be installed, and folders in the X11
+ directory may be uninstalled or disabled (i.e. the folder is not deleted, but it's entry is removed from
+ the XF86Config file).
+15. No longer supply .enc files with KFontinst - they should be provided by the distro.
+
+0.9.1->0.9.2
+============
+1. Removed a bug where the "Configure System" menu entry was always disabled!
+2. Spelling error in Settings dialog.
+3. t1lib has problems with some of the fonts supplied with Adobe acrobat - therefore, if t1lib fails to load the
+ font, then KFontinst itself will try to read the header information (although no preview will be available,
+ everything else should still work).
+4. Fixed multiple installing of programs in other/ directory. For instance KFontinst's version of ttmkfdir
+ was being installed into $(PREFIX) (usually /usr/bin) as well as $(KDE_DATADIR)/kfontinst - this was incorrect
+ as KFontinst will only use the version in $(KDE_DATADIR)/kfontinst, and it was possible that a previous version
+ of ttmkfdir (such as that supplied with XFree86) would have been overwritten.
+5. Fixed bug where the user was allowed to select (and subsequently install) fonts which could not be loaded correctly.
+6. Added the ability to enter a custom preview string.
+
+0.9->0.9.1
+==========
+1. Fixed a few compile errors.
+2. Fix to html formatting error.
+3. Fixed a ./configure error if t1lib was not found (the string NO was being used as the
+ librarary name, instead of an empty string!)
+4. Modified the reading of Type1 header information.
+
+0.8.3->0.9
+==========
+1. Converted to KDE2.
+2. Rearranged this file!
+3. Removed command line interface - KDE2's command line stuff is way different!
+4. Re-created dialogs with Qt designer.
+5. Removed ProgressDialog, and replaced with a progress bar on a new statusbar.
+6. Modified configure script to check for FreeType & t1lib.
+7. If an encoding (not unicode) is selected, then the .enc file is copied to the X11 fonts directory.
+8. As with the .enc files, the StarOffice .xpp files are also copied, and no longer just sym linked.
+9. Removed enabling/disabing of Configure System button.
+10. Fontmap.X11 is no longer created, instead the real Fontmap file itself is modified.
+
+0.8.2->0.8.3
+============
+1. Modified 'kfontinst.kdelnk' so that kdesu is now used - so that a user will automatically be prompted
+ for the root password.
+2. Modified dialogs to use the KDE caption ("Font Installer") instead of the app name ("kfontinst")
+3. Corrected size of Configure dialog.
+4. Fixed a minor bug where if all fonts were uninstalled, the 'Configure System' button was disabled - therefore not
+ allowing you to activate the changes!
+5. Added a command line interface. (type 'kfontinst --help' for details)
+6. Added option to automatically fix TTF postscript names upon install.
+
+0.8.1->0.8.2
+============
+1. Fixed a bug which always had SO configuration disabled!
+2. Fixed a bug when selecting Unicode encoding.
+3. Changed "Fonts/Uninstalled" menu entry to "Fonts/Disk"
+4. Added keyboard short-cuts to dialogs
+
+0.8->0.8.1
+==========
+1. Fixed a bug where X configuration would fail if no TT fonts present.
+2. If no fonts are installed, then the system configuration button/menu-entry is now disabled.
+3. Changed menu structure to add 'Fonts' menu.
+
+0.7.4->0.8
+==========
+1. Changed location of StarOffice stuf from <dir on settings dialog>/xp3 to just
+ <dir on settings dialog> -- As StarOffice 5.2 has 'xp3' within a 'share' sub-dir.
+2. Changed structure of config file to be more modular.
+3. Modified internal code structure to allow easier additon of extra apps to be configured. (NOTE: If any
+ apps need to be configured, then I'll also [later on] modify the Settings & Configure dialogs to
+ accomodate these.)
+4. Because of 3, added a 'StarOffice' check to the settings dialog. If this is not seleted, then no check
+ is performed to make sure the SO dir is OK - and the option to config SO is diabled on the config dialog.
+5. Added check when installing font to make sure that it's not already installed.
+
+0.7.3->0.7.4
+============
+1. Changed location of Fontmap.X11 -- from <directory on settings dialog>/lib/Fontmap.X11 to
+ <directory on settings dialog>/Fontmap.X11. As it seems some ghostscript installations don't
+ have the 'lib' sub directory.
+2. Improved the documentation a little - added a FAQ section
+
+0.7.2->0.7.3
+============
+1. Very minor bug fix.
+
+0.7.1->0.7.2
+============
+1. Added more detailed error messages when system configuration fails.
+
+0.7->0.7.1
+==========
+1. Removed lots of debug info from ttf2pt1, and afm.pl -- this should drastically speed up afm creation.
+2. Modified ttf2pt1 to accept a parameter to just create .afm files
+3. Added option to modify a .afm file when installing.
+4. Added "Unicode" to list of encodings that can be used.
+5. Removed kfontinst-cp1252.enc, kfontinst-cp1252.xpp -- these were hacks anyway, and seing as Qt2 is going to
+ support cp1252 by a hard-coded codec, there's no real point...
+6. Rearranged the Configure System dialog - so that Force AFM regeneration is grouped next to the Generate AFMs option.
+7. Encoding files now stored in <KDEDIR>/share/apps/kfontinst/Encodings
+
+0.6.1->0.7
+==========
+1. Modified ttmkfdir & ttf2pt1 to allow usage of X11 style font re-encoding files.
+2. Because .enc files are now used by kfontinst, removed the possibility of using gzipped encodings.
+3. Added the ability to delete an installed font's .afm file.
+4. Fixed a bug in the TtfPsNameFixer class - this would cause ttf2pt1 to creash when accessing a modified font!
+5. Font encodings are now stored in <KDEDir>/share/x11encodings
+6. Removed the reencode shell script, as the encodng is all done by ttmkfdir.
+7. Removed xfinst shell script - handled internally.
+8. Supplied a kfontinst-cp1252 encoding - with the ugly single-quotes normaly found in .ttf files remapped to
+ the nice looking ones.
+9. Added functionality, when configuring StarOffice, to select an appropriate xprinter.prolog for the selected
+ encoding (if one exists)...
+
+0.6->0.6.1
+==========
+1. Fixed a display bug in the 'Un/Exclude from StarOffice" options.
+
+0.5->0.6
+========
+1. Added the ability to 'fix' the postscript names in a ttf file.
+2. Fixed some missing changes to help files.
+
+0.4->0.5
+========
+1. Discovered a patch that modifies StarOffice's xprinter.prolog so that font's don't need to be modified
+ to use the microsoft cp1252 enocding scheme. (Previosuly the PS output from StarOffice would not print
+ OK with ghostscript - when using extra characters - unless the .ttf file was modified.)
+2. Because of 1, removed the abilty to modify a TrueType font's internal charactermap - this was a hack anyway.
+3. xfinst now uses mkfontdir to create encodings.dir - instead of kfontinst's install procedure copying a standard
+ one in (this didn't actually work...)
+4. As kfontinst no longer reads the .enc files themselves, added the ability to use .enc.gz files as well
+ when selecting an encoding for X.
+5. Re-wrote xfinst & reencode to be plain 'sh' scripts, as opposed to 'tcsh' scripts.
+
+0.3->0.4
+========
+1. All X fonts will now be placed with in a directory - "Managed" - this makes things easier for
+ AbiWord, and maybe others.
+2. encodings.dir & Encodings/ will now be placed within this new "Managed" dir.
+3. Only 1 StarOffice .PS file will be created - X11.PS
+4. Only 1 Fontmap will be created - Fontmap.X11 - and this will be placed within
+ <Ghostscript>/lib
+5. Because of 4, an option has been added to the Settings dialog to specify the location of
+ Ghostscript.
+6. Because of 1, removed the font option from the Configure dialog.
+7. Fixed an error with getting PS name from TT font - PS names are not allowed to have spaces, but in
+ fences.ttf it does. FontEngine.cpp will now check for, and fix, this - using the same 'algorithm' as that
+ of ttf2pt1 (which means the names will tie up with those in the .afm files).
+8. Added some improvements to control of dialogs.
+
+0.2.1->0.3
+==========
+1. Reverted back to naming .afm files <fontname>.afm - and renaming any conflicting fonts.
+2. Speeded up copying of files - by copying preview bitmap as opposed to regenerating it!
+3. Removed need for FontMetrics directory - .afm files now placed within TrueType or Type1 dir,
+ and sym links are produced for StarOffice.
+
+ 1. & 3. should now make things easier for AbiWord.
+
+4. Fixed output of Fontmap so that "URW Gothic" will be aliased as "UrwGothic-Roman" (etc.) as
+ this is what Qt will output.
+5. Added more processing of .afm files - this makes them OK for AbiWord.
+
+0.2->0.2.1
+==========
+1. Modified start-up progress dailog, and added progress dialogs to main window when scanning
+ fonts. These will only appear if numTTfonts>X || numT1fonts>Y
+
+0.1->0.2
+========
+1. Combined views of installed TrueType and Type1 fonts into 1 list.
+2. When uninstalling a font, can now move the font to another directory - or delete.
+3. Used t1lib so that Type1 fonts can also be previewed.
+4. Changed Fontmap creator to dynamically allocate memory for each font-category.
+5. .afm files are now named as <fontname>.<fontextension>.afm - this removes the need
+ for renaming the .afm file if there exists Type1 and TrueType fonts with the same
+ fontname.
+6. Removed the re-scanning of the install directories whenever a font is added.
+7. Added support for extra Type1 font weights.
+8. Added a start-up screen to inform the user that the installed/disk fonts are being scanned.
+9. When exiting, confirmation is now only asked if the system has been changed and not
+ reconfigured.
diff --git a/kcontrol/kfontinst/Makefile.am b/kcontrol/kfontinst/Makefile.am
new file mode 100644
index 000000000..963ec3c93
--- /dev/null
+++ b/kcontrol/kfontinst/Makefile.am
@@ -0,0 +1,14 @@
+if include_fontinst_tn
+FONTINST_TN_SUBDIR=thumbnail
+FONTINST_VP_SUBDIR=viewpart
+endif
+
+SUBDIRS = lib $(FONTINST_TN_SUBDIR) $(FONTINST_VP_SUBDIR) kcmfontinst kfile-plugin kfontinst kio
+
+EXTRA_DIST = TODO
+
+konqservicedir = $(kde_datadir)/konqueror/servicemenus
+konqservice_DATA = installfont.desktop
+
+messages: rc.cpp
+ $(XGETTEXT) rc.cpp */*.cpp */*.h -o $(podir)/kfontinst.pot
diff --git a/kcontrol/kfontinst/TODO b/kcontrol/kfontinst/TODO
new file mode 100644
index 000000000..94466e61c
--- /dev/null
+++ b/kcontrol/kfontinst/TODO
@@ -0,0 +1 @@
+1. Support other X server config file types - if there are any other types...
diff --git a/kcontrol/kfontinst/configure.in.bot b/kcontrol/kfontinst/configure.in.bot
new file mode 100644
index 000000000..99042cbdb
--- /dev/null
+++ b/kcontrol/kfontinst/configure.in.bot
@@ -0,0 +1,12 @@
+dnl put here things which have to be done as very last part of configure
+
+if test -z "$FONTINST_SUBDIR"; then
+ echo ""
+ echo "KFontInstall control module got disabled from compilation"
+ echo "because of missing FreeType 2.x libraries/headers."
+ echo "You can download the freetype library from http://www.freetype.org/."
+ echo ""
+ all_tests=bad
+fi
+
+
diff --git a/kcontrol/kfontinst/configure.in.in b/kcontrol/kfontinst/configure.in.in
new file mode 100644
index 000000000..df6d3d34c
--- /dev/null
+++ b/kcontrol/kfontinst/configure.in.in
@@ -0,0 +1,155 @@
+FONTINST_SUBDIR=""
+FONTINST_TN=""
+
+# Check for FreeType...
+KFI_FOUND_FREETYPE=0
+
+KDE_FIND_PATH(freetype-config, FREETYPE_CONFIG, [${prefix}/bin ${exec_prefix}/bin /usr/bin /usr/local/bin /opt/local/bin], [
+ AC_MSG_WARN([Could not find libfreetype anywhere, check http://www.freetype.org/])
+ ])
+
+if test -n "$FREETYPE_CONFIG"; then
+ vers=`$FREETYPE_CONFIG --version 2>/dev/null | sed -e 's/libfreetype //' | awk 'BEGIN { FS = "."; } { printf "%d", ($1 * 1000 + $2) * 1000 + $3;}'`
+ if test -n "$vers" && test "$vers" -ge 9002003
+ then
+ LIBFREETYPE_LIBS="`$FREETYPE_CONFIG --libs`"
+ LIBFREETYPE_RPATH=
+ for args in $LIBFREETYPE_LIBS; do
+ case $args in
+ -L*)
+ LIBFREETYPE_RPATH="$LIBFREETYPE_RPATH $args"
+ ;;
+ esac
+ done
+ LIBFREETYPE_RPATH=`echo $LIBFREETYPE_RPATH | sed -e "s/-L/-R/g"`
+ LIBFREETYPE_CFLAGS="`$FREETYPE_CONFIG --cflags`"
+ KFI_FOUND_FREETYPE=1
+ else
+ AC_MSG_WARN([You need at least FreeType 2.1.3])
+ fi
+fi
+
+if test "$KFI_FOUND_FREETYPE" -eq 1; then
+ AC_SUBST(LIBFREETYPE_LIBS)
+ AC_SUBST(LIBFREETYPE_CFLAGS)
+ AC_SUBST(LIBFREETYPE_RPATH)
+
+ KFI_FOUND_FONTCONFIG=0
+ # check for fontconfig...
+ KDE_FIND_PATH(fontconfig-config, FONTCONFIG_CONFIG, [${prefix}/bin ${exec_prefix}/bin /usr/bin /usr/local/bin /opt/local/bin], [
+ KDE_FIND_PATH(pkg-config, PKGCONFIG, [${prefix}/bin ${exec_prefix}/bin /usr/bin /usr/local/bin /opt/local/bin], [
+ AC_MSG_WARN([Could not find neither pkg-config nor fontconfig-config, check http://www.fontconfig.org/ ])
+ ])
+ ])
+
+ if test -n "$PKGCONFIG"; then
+ vers=`$PKGCONFIG fontconfig --modversion 2>/dev/null | sed -e 's/libfontconfig //' | awk 'BEGIN { FS = "."; } { printf "%d", ($1 * 1000 + $2) * 1000 + $3;}'`
+ if test -n "$vers" && test "$vers" -ge 2000000 ; then
+ LIBFONTCONFIG_LIBS="`$PKGCONFIG fontconfig --libs`"
+ LIBFONTCONFIG_RPATH=
+ for args in $LIBFONTCONFIG_LIBS; do
+ case $args in
+ -L*)
+ LIBFONTCONFIG_RPATH="$LIBFONTCONFIG_RPATH $args"
+ ;;
+ esac
+ done
+ LIBFONTCONFIG_RPATH=`echo $LIBFONTCONFIG_RPATH | sed -e "s/-L/-R/g"`
+ LIBFONTCONFIG_CFLAGS="`$PKGCONFIG fontconfig --cflags`"
+ KFI_FOUND_FONTCONFIG=1
+ fi
+ fi
+
+ if test -n "$FONTCONFIG_CONFIG"; then
+ vers=`$FONTCONFIG_CONFIG --version 2>/dev/null | sed -e 's/libfontconfig //' | awk 'BEGIN { FS = "."; } { printf "%d", ($1 * 1000 + $2) * 1000 + $3;}'`
+ if test -n "$vers" && test "$vers" -ge 2000000 ; then
+ LIBFONTCONFIG_LIBS="`$FONTCONFIG_CONFIG --libs`"
+ LIBFONTCONFIG_RPATH=
+ for args in $LIBFONTCONFIG_LIBS; do
+ case $args in
+ -L*)
+ LIBFONTCONFIG_RPATH="$LIBFONTCONFIG_RPATH $args"
+ ;;
+ esac
+ done
+ LIBFONTCONFIG_RPATH=`echo $LIBFONTCONFIG_RPATH | sed -e "s/-L/-R/g"`
+ LIBFONTCONFIG_CFLAGS="`$FONTCONFIG_CONFIG --cflags`"
+ KFI_FOUND_FONTCONFIG=1
+ fi
+ fi
+
+ if test "$KFI_FOUND_FONTCONFIG" -eq 1; then
+ AC_SUBST(LIBFONTCONFIG_LIBS)
+ AC_SUBST(LIBFONTCONFIG_CFLAGS)
+ AC_SUBST(LIBFONTCONFIG_RPATH)
+
+ # Check OS...
+ AC_MSG_CHECKING([OS])
+ case "$host" in
+ *-*-linux*) UNAME='Linux' ;;
+ *-*-freebsd*) UNAME='FreeBSD' ;;
+ *-*-kfreebsd-gnu*) UNAME='GNU/kFreeBSD' ;;
+ *-*-netbsd*) UNAME='NetBSD' ;;
+ *-*-solaris*) UNAME='Solaris' ;;
+ *-*-irix*) UNAME='Irix' ;;
+ *-*-aix*) UNAME='AIX' ;;
+ *-*-hpux*) UNAME='HPUX' ;;
+ *-*-darwin*) UNAME='Darwin' ;;
+ *) UNAME='Unknown' ;;
+ esac
+ AC_MSG_RESULT($UNAME)
+ AC_SUBST(UNAME)
+
+ # Check for fontenc...
+ ac_font_enc_headers=0
+ KDE_CHECK_HEADER(X11/fonts/fontenc.h,[ac_font_enc_headers=1])
+ if test "$ac_font_enc_headers" = "0"; then
+ AC_MSG_WARN(FontEnc headers not found. FontEnc support disabled)
+ else
+ ac_LDFLAGS_save="$LDFLAGS"
+ ld_shared_flag=
+ KDE_CHECK_COMPILER_FLAG(shared, [ld_shared_flag="-shared"])
+ LDFLAGS="$LDFLAGS $ld_shared_flag $all_libraries -lz"
+ KDE_CHECK_LIB(fontenc,FontEncDirectory,ac_font_enc_lib=1,ac_font_enc_lib=0)
+ if test "$ac_font_enc_lib" = "1"; then
+ LIB_FONT_ENC="-lfontenc"
+ AC_DEFINE(HAVE_FONT_ENC, 1, [Defines if you have FontEnc])
+ fi
+ LDFLAGS="$ac_LDFLAGS_save"
+ fi
+ AC_SUBST(LIB_FONT_ENC)
+
+ FONTINST_SUBDIR="kfontinst"
+ # Check for Xft...
+ ac_xft_headers=0
+ ac_CXXFLAGS_save="$CXXFLAGS"
+ ac_CFLAGS_save="$CFLAGS"
+ ac_CPPFLAGS_save="$CPPFLAGS"
+ CXXFLAGS="$CXXFLAGS $all_includes $USER_INCLUDES $LIBFREETYPE_CFLAGS"
+ CFLAGS="$CXXFLAGS"
+ CPPFLAGS="$CXXFLAGS"
+
+ AC_CHECK_HEADER(X11/Xft/Xft.h, [ac_xft_headers=1])
+ if test "$ac_xft_headers" -eq 1 ; then
+ LIBXFT_LIB=-lXft
+ AC_SUBST(LIBXFT_LIB)
+ else
+ AC_MSG_WARN([Missing Xft headers - disabling font previews!])
+ fi
+ CXXFLAGS="$ac_CXXFLAGS_save"
+ CFLAGS="$ac_CFLAGS_save"
+ CPPFLAGS="$ac_CPPFLAGS_save"
+ else
+ AC_MSG_WARN([Missing FontConfig - disabling kfontinst!])
+ fi
+else
+ AC_MSG_WARN([Missing FreeType2 - disabling kfontinst!])
+fi
+
+AM_CONDITIONAL(include_fontinst_tn, test "$ac_xft_headers" -eq 1)
+
+if test "$ac_xft_headers" -eq 1 ; then
+ AC_DEFINE(HAVE_XFT, 1, [Defines if you have Xft])
+fi
+
+AM_CONDITIONAL(include_kcontrol_kfontinst, test -n "$FONTINST_SUBDIR")
diff --git a/kcontrol/kfontinst/installfont.desktop b/kcontrol/kfontinst/installfont.desktop
new file mode 100644
index 000000000..5286ce4ec
--- /dev/null
+++ b/kcontrol/kfontinst/installfont.desktop
@@ -0,0 +1,79 @@
+[Desktop Entry]
+ServiceTypes=application/x-font-ttf,application/x-font-type1,application/x-font-speedo,application/x-font-bdf,application/x-font-pcf,application/x-font-snf,application/x-font-otf,application/x-font-ttc,application/x-afm
+Actions=installFont;
+
+[Desktop Action installFont]
+Name=Install
+Name[af]=Installeer
+Name[ar]=ثبت
+Name[be]=Устанавіць
+Name[bg]=Инсталиране
+Name[bn]=ইনস্টল
+Name[br]=Staliañ
+Name[bs]=Instaliraj
+Name[ca]=Instal·la
+Name[cs]=Instalovat
+Name[csb]=Instalëjë
+Name[cy]=Gosod
+Name[da]=Installér
+Name[de]=Installieren
+Name[el]=Εγκατάσταση
+Name[eo]=Instali
+Name[es]=Instalar
+Name[et]=Paigaldamine
+Name[eu]=Instalatu
+Name[fa]=نصب
+Name[fi]=Asenna
+Name[fr]=Installer
+Name[fy]=Ynstallearje
+Name[ga]=Suiteáil
+Name[gl]=Instalar
+Name[he]=התקנה
+Name[hi]=संस्थापित
+Name[hr]=Instaliraj
+Name[hu]=Telepítő
+Name[is]=Setja upp
+Name[it]=Installa
+Name[ja]=インストール
+Name[ka]=ინსტალაცია
+Name[kk]=Орнату
+Name[km]=ដំឡើង
+Name[ko]=설치...
+Name[lt]=Įdiegti
+Name[lv]=Instalēt
+Name[mk]=Инсталирај
+Name[ms]=Pasang
+Name[mt]=Installa
+Name[nb]=Installer
+Name[nds]=Installeren
+Name[ne]=स्थापना गर्नुहोस्
+Name[nl]=Installeren
+Name[nn]=Installer
+Name[pa]=ਇੰਸਟਾਲ
+Name[pl]=Instaluj
+Name[pt]=Instalar
+Name[pt_BR]=Instalar
+Name[ro]=Instalare
+Name[ru]=Установка
+Name[rw]=Kwinjizaporogaramu
+Name[se]=Sajáiduhte
+Name[sk]=Inštalácia
+Name[sl]=Namesti
+Name[sr]=Инсталирај
+Name[sr@Latn]=Instaliraj
+Name[sv]=Installera
+Name[ta]=நிறுவி
+Name[te]=స్థాపించు
+Name[tg]=Гузоштан
+Name[th]=ติดตั้ง
+Name[tr]=Kur
+Name[tt]=Quyu
+Name[uk]=Встановлення
+Name[uz]=Oʻrnatish
+Name[uz@cyrillic]=Ўрнатиш
+Name[vi]=Cài đặt
+Name[wa]=Astaler
+Name[zh_CN]=安装
+Name[zh_TW]=安裝
+Icon=fonts
+Exec=kfmclient copy %U fonts:/
diff --git a/kcontrol/kfontinst/kcmfontinst/KCmFontInst.cpp b/kcontrol/kfontinst/kcmfontinst/KCmFontInst.cpp
new file mode 100644
index 000000000..4a6b0b3ee
--- /dev/null
+++ b/kcontrol/kfontinst/kcmfontinst/KCmFontInst.cpp
@@ -0,0 +1,647 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : KFI::CKCmFontInst
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 26/04/2003
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2003, 2004
+////////////////////////////////////////////////////////////////////////////////
+
+#include "KCmFontInst.h"
+#include "KfiConstants.h"
+#include "PrintDialog.h"
+#include "SettingsDialog.h"
+#ifdef HAVE_XFT
+#include "KfiPrint.h"
+#include "FcEngine.h"
+#endif
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qpainter.h>
+#include <qpaintdevicemetrics.h>
+#include <qsettings.h>
+#include <kaboutdata.h>
+#include <kgenericfactory.h>
+#include <kdiroperator.h>
+#include <kprinter.h>
+#include "Misc.h"
+#include "KFileFontIconView.h"
+#include "KFileFontView.h"
+#include <kpopupmenu.h>
+#include <ktoolbar.h>
+#include <ktoolbarbutton.h>
+#include <kstdaccel.h>
+#include <kfiledialog.h>
+#include <kmessagebox.h>
+#include <kcmdlineargs.h>
+#include <kapplication.h>
+#include <kio/job.h>
+#include <kio/netaccess.h>
+#include <kdirlister.h>
+#include <kpushbutton.h>
+#include <kguiitem.h>
+#include <qsplitter.h>
+
+#define CFG_GROUP "Main Settings"
+#define CFG_LISTVIEW "ListView"
+#define CFG_PATH "Path"
+#define CFG_SPLITTER_SIZES "SplitterSizes"
+#define CFG_SHOW_BITMAP "ShowBitmap"
+#define CFG_FONT_SIZE "FontSize"
+
+typedef KGenericFactory<KFI::CKCmFontInst, QWidget> FontInstallFactory;
+K_EXPORT_COMPONENT_FACTORY(kcm_fontinst, FontInstallFactory("kcmfontinst"))
+
+namespace KFI
+{
+
+CKCmFontInst::CKCmFontInst(QWidget *parent, const char *, const QStringList&)
+ : KCModule(parent, "kfontinst"),
+#ifdef HAVE_XFT
+ itsPreview(NULL),
+#endif
+ itsConfig(KFI_UI_CFG_FILE)
+{
+ KGlobal::locale()->insertCatalogue(KFI_CATALOGUE);
+
+ KAboutData* about = new KAboutData("kcmfontinst",
+ I18N_NOOP("KDE Font Installer"),
+ 0, 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("GUI front end to the fonts:/ ioslave.\n"
+ "(c) Craig Drummond, 2000 - 2004"));
+ about->addAuthor("Craig Drummond", I18N_NOOP("Developer and maintainer"), "craig@kde.org");
+ setAboutData(about);
+
+ const char *appName=KCmdLineArgs::appName();
+
+ itsEmbeddedAdmin=Misc::root() && (NULL==appName || strcmp("kcontrol", appName) &&
+ KCmdLineArgs::parsedArgs()->isSet("embed"));
+
+ itsStatusLabel = new QLabel(this);
+ itsStatusLabel->setFrameShape(QFrame::Panel);
+ itsStatusLabel->setFrameShadow(QFrame::Sunken);
+ itsStatusLabel->setLineWidth(1);
+
+ itsConfig.setGroup(CFG_GROUP);
+
+ QFrame *fontsFrame;
+#ifdef HAVE_XFT
+ KLibFactory *factory=KLibLoader::self()->factory("libkfontviewpart");
+
+ if(factory)
+ {
+ itsSplitter=new QSplitter(this);
+ fontsFrame=new QFrame(itsSplitter),
+ itsPreview=(KParts::ReadOnlyPart *)factory->create(itsSplitter, "kcmfontinst", "KParts::ReadOnlyPart");
+ itsSplitter->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
+
+ QValueList<int> sizes(itsConfig.readIntListEntry(CFG_SPLITTER_SIZES));
+
+ if(2!=sizes.count())
+ {
+ sizes.clear();
+ sizes+=250;
+ sizes+=150;
+ }
+ itsSplitter->setSizes(sizes);
+ }
+ else
+ {
+#endif
+ fontsFrame=new QFrame(this);
+ fontsFrame->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
+#ifdef HAVE_XFT
+ }
+#endif
+
+ QGridLayout *fontsLayout=new QGridLayout(fontsFrame, 1, 1, 0, 1);
+ QVBoxLayout *layout=new QVBoxLayout(this, 0, KDialog::spacingHint());
+ KToolBar *toolbar=new KToolBar(this);
+ bool showBitmap(itsConfig.readBoolEntry(CFG_SHOW_BITMAP, false));
+
+ fontsFrame->setLineWidth(0);
+ toolbar->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
+ toolbar->setMovingEnabled(false);
+
+ QString previousPath=itsConfig.readEntry(CFG_PATH);
+
+ itsDirOp = new KDirOperator(Misc::root() ? QString("fonts:/") : QString("fonts:/")+i18n(KFI_KIO_FONTS_USER),
+ fontsFrame);
+ itsDirOp->setViewConfig(&itsConfig, "ListView Settings");
+ itsDirOp->setMinimumSize(QSize(96, 64));
+ setMimeTypes(showBitmap);
+ itsDirOp->dirLister()->setMainWindow(this);
+ itsDirOp->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
+ fontsLayout->addMultiCellWidget(itsDirOp, 0, 0, 0, 1);
+
+ KPushButton *button=new KPushButton(KGuiItem(i18n("Add Fonts..."), "newfont"), fontsFrame);
+ connect(button, SIGNAL(clicked()), SLOT(addFonts()));
+ button->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+ fontsLayout->addWidget(button, 1, 0);
+ fontsLayout->addItem(new QSpacerItem(4, 4, QSizePolicy::Expanding, QSizePolicy::Minimum));
+
+ layout->addWidget(toolbar);
+#ifdef HAVE_XFT
+ layout->addWidget(itsPreview ? itsSplitter : fontsFrame);
+#else
+ layout->addWidget(fontsFrame);
+#endif
+ layout->addWidget(itsStatusLabel);
+
+ setButtons(0);
+ setRootOnlyMsg(i18n("<b>The fonts shown are your personal fonts.</b><br>To see (and install) "
+ "system-wide fonts, click on the \"Administrator Mode\" button below."));
+ setUseRootOnlyMsg(true);
+ itsDirOp->setMode(KFile::Files);
+
+ //
+ // Now for the hack!
+ KAction *act;
+ KActionMenu *topMnu=dynamic_cast<KActionMenu *>(itsDirOp->actionCollection()->action("popupMenu"));
+
+ itsViewMenuAct=dynamic_cast<KActionMenu *>(itsDirOp->actionCollection()->action("view menu"));
+ topMnu->popupMenu()->clear();
+ connect(topMnu->popupMenu(), SIGNAL(aboutToShow()), SLOT(setupMenu()));
+ if((act=itsDirOp->actionCollection()->action("up")))
+ act->disconnect(SIGNAL(activated()), itsDirOp, SLOT(cdUp()));
+ if((act=itsDirOp->actionCollection()->action("home")))
+ act->disconnect(SIGNAL(activated()), itsDirOp, SLOT(home()));
+ if((act=itsDirOp->actionCollection()->action("back")))
+ act->disconnect(SIGNAL(activated()), itsDirOp, SLOT(back()));
+ if((act=itsDirOp->actionCollection()->action("forward")))
+ act->disconnect(SIGNAL(activated()), itsDirOp, SLOT(forward()));
+
+ if((act=itsDirOp->actionCollection()->action("reload")))
+ act->plug(toolbar);
+
+ topMnu->insert(itsViewMenuAct);
+
+ if((itsIconAct=dynamic_cast<KRadioAction *>(itsDirOp->actionCollection()->action("short view"))))
+ {
+ disconnect(itsIconAct, SIGNAL(activated()), itsDirOp, SLOT(slotSimpleView()));
+ connect(itsIconAct, SIGNAL(activated()), SLOT(iconView()));
+ itsIconAct->plug(toolbar);
+ }
+
+ if((itsListAct=dynamic_cast<KRadioAction *>(itsDirOp->actionCollection()->action("detailed view"))))
+ {
+ disconnect(itsListAct, SIGNAL(activated()), itsDirOp, SLOT(slotDetailedView()));
+ connect(itsListAct, SIGNAL(activated()), SLOT(listView()));
+ itsListAct->plug(toolbar);
+ }
+
+ itsShowBitmapAct=new KToggleAction(i18n("Show Bitmap Fonts"), "font_bitmap", 0, this, SLOT(filterFonts()),
+ itsDirOp->actionCollection(), "showbitmap");
+ itsShowBitmapAct->setChecked(showBitmap);
+ itsShowBitmapAct->plug(toolbar);
+
+ toolbar->insertLineSeparator();
+
+ act=new KAction(i18n("Add Fonts..."), "newfont", 0, this, SLOT(addFonts()), itsDirOp->actionCollection(), "addfonts");
+ act->plug(toolbar);
+ topMnu->insert(act);
+
+ if((itsDeleteAct=itsDirOp->actionCollection()->action("delete")))
+ {
+ itsDeleteAct->plug(toolbar);
+ itsDeleteAct->setEnabled(false);
+ topMnu->insert(itsDeleteAct);
+ disconnect(itsDeleteAct, SIGNAL(activated()), itsDirOp, SLOT(deleteSelected()));
+ connect(itsDeleteAct, SIGNAL(activated()), this, SLOT(removeFonts()));
+ }
+
+ toolbar->insertLineSeparator();
+ act=new KAction(i18n("Configure..."), "configure", 0, this, SLOT(configure()), itsDirOp->actionCollection(), "configure");
+ act->plug(toolbar);
+#ifdef HAVE_XFT
+ toolbar->insertLineSeparator();
+ act=new KAction(i18n("Print..."), "fileprint", 0, this, SLOT(print()), itsDirOp->actionCollection(), "print");
+ act->plug(toolbar);
+#endif
+
+ if( (itsSepDirsAct=itsDirOp->actionCollection()->action("separate dirs")) &&
+ (itsShowHiddenAct=itsDirOp->actionCollection()->action("show hidden")))
+ {
+ //disconnect(itsViewMenuAct->popupMenu(), SIGNAL(aboutToShow()), itsDirOp, SLOT(insertViewDependentActions()));
+ connect(itsViewMenuAct->popupMenu(), SIGNAL(aboutToShow()), SLOT(setupViewMenu()));
+ setupViewMenu();
+ }
+
+#ifdef HAVE_XFT
+ if(itsPreview)
+ {
+ KActionCollection *previewCol=itsPreview->actionCollection();
+
+ if(previewCol && previewCol->count()>0 && (act=previewCol->action("changeText")))
+ act->plug(toolbar);
+ }
+#endif
+
+ //
+ // Set view...
+ if(itsConfig.readBoolEntry(CFG_LISTVIEW, true))
+ listView();
+ else
+ iconView();
+
+ itsDirOp->dirLister()->setShowingDotFiles(true);
+
+ connect(itsDirOp, SIGNAL(fileHighlighted(const KFileItem *)), SLOT(fileHighlighted(const KFileItem *)));
+ connect(itsDirOp, SIGNAL(finishedLoading()), SLOT(loadingFinished()));
+ connect(itsDirOp, SIGNAL(dropped(const KFileItem *, QDropEvent *, const KURL::List &)),
+ SLOT(dropped(const KFileItem *, QDropEvent *, const KURL::List &)));
+ connect(itsDirOp->dirLister(), SIGNAL(infoMessage(const QString &)), SLOT(infoMessage(const QString &)));
+ connect(itsDirOp, SIGNAL(updateInformation(int, int)), SLOT(updateInformation(int, int)));
+}
+
+CKCmFontInst::~CKCmFontInst()
+{
+#ifdef HAVE_XFT
+ if(itsPreview)
+ {
+ itsConfig.setGroup(CFG_GROUP);
+ itsConfig.writeEntry(CFG_SPLITTER_SIZES, itsSplitter->sizes());
+ }
+#endif
+ delete itsDirOp;
+}
+
+void CKCmFontInst::setMimeTypes(bool showBitmap)
+{
+ QStringList mimeTypes;
+
+ mimeTypes << "application/x-font-ttf"
+ << "application/x-font-otf"
+ << "application/x-font-ttc"
+ << "application/x-font-type1";
+ if(showBitmap)
+ mimeTypes << "application/x-font-pcf"
+ << "application/x-font-bdf";
+
+ itsDirOp->setMimeFilter(mimeTypes);
+}
+
+void CKCmFontInst::filterFonts()
+{
+ setMimeTypes(itsShowBitmapAct->isChecked());
+ itsDirOp->rereadDir();
+ itsConfig.setGroup(CFG_GROUP);
+ itsConfig.writeEntry(CFG_SHOW_BITMAP, itsShowBitmapAct->isChecked());
+ if(itsEmbeddedAdmin)
+ itsConfig.sync();
+}
+
+QString CKCmFontInst::quickHelp() const
+{
+ return Misc::root()
+ ? i18n("<h1>Font Installer</h1><p> This module allows you to"
+ //" install TrueType, Type1, Speedo, and Bitmap"
+ " install TrueType, Type1, and Bitmap"
+ " fonts.</p><p>You may also install fonts using Konqueror:"
+ " type fonts:/ into Konqueror's location bar"
+ " and this will display your installed fonts. To install a"
+ " font, simply copy one into the folder.</p>")
+ : i18n("<h1>Font Installer</h1><p> This module allows you to"
+ //" install TrueType, Type1, Speedo, and Bitmap"
+ " install TrueType, Type1, and Bitmap"
+ " fonts.</p><p>You may also install fonts using Konqueror:"
+ " type fonts:/ into Konqueror's location bar"
+ " and this will display your installed fonts. To install a"
+ " font, simply copy it into the appropriate folder - "
+ " \"Personal\" for fonts available to just yourself, or "
+ " \"System\" for system-wide fonts (available to all).</p>"
+ "<p><b>NOTE:</b> As you are not logged in as \"root\", any"
+ " fonts installed will only be available to you. To install"
+ " fonts system-wide, use the \"Administrator Mode\""
+ " button to run this module as \"root\".</p>");
+}
+
+void CKCmFontInst::listView()
+{
+ CKFileFontView *newView=new CKFileFontView(itsDirOp, "detailed view");
+
+ itsDirOp->setView(newView);
+ itsListAct->setChecked(true);
+ itsConfig.setGroup(CFG_GROUP);
+ itsConfig.writeEntry(CFG_LISTVIEW, true);
+ if(itsEmbeddedAdmin)
+ itsConfig.sync();
+ itsDirOp->setAcceptDrops(true);
+}
+
+void CKCmFontInst::iconView()
+{
+ CKFileFontIconView *newView=new CKFileFontIconView(itsDirOp, "simple view");
+
+ itsDirOp->setView(newView);
+ itsIconAct->setChecked(true);
+ itsConfig.setGroup(CFG_GROUP);
+ itsConfig.writeEntry(CFG_LISTVIEW, false);
+ if(itsEmbeddedAdmin)
+ itsConfig.sync();
+ itsDirOp->setAcceptDrops(true);
+}
+
+void CKCmFontInst::setupMenu()
+{
+ itsDirOp->setupMenu(KDirOperator::SortActions|/*KDirOperator::FileActions|*/KDirOperator::ViewActions);
+}
+
+void CKCmFontInst::setupViewMenu()
+{
+ itsViewMenuAct->remove(itsSepDirsAct);
+ itsViewMenuAct->remove(itsShowHiddenAct);
+}
+
+void CKCmFontInst::fileHighlighted(const KFileItem *item)
+{
+ const KFileItemList *list=itsDirOp->selectedItems();
+
+ itsDeleteAct->setEnabled(list && list->count());
+
+#ifdef HAVE_XFT
+ if(itsPreview)
+ {
+ //
+ // Generate preview...
+ const KFileItem *previewItem=item
+ ? item
+ : list && 1==list->count()
+ ? list->getFirst()
+ : NULL;
+
+ if(previewItem && list && list->contains(previewItem)) // OK, check its been selected - not deselected!!!
+ itsPreview->openURL(previewItem->url());
+ }
+#endif
+}
+
+void CKCmFontInst::loadingFinished()
+{
+ QListView *lView=dynamic_cast<QListView *>(itsDirOp->view());
+
+ if(lView)
+ lView->sort();
+ else
+ {
+ QIconView *iView=dynamic_cast<QIconView *>(itsDirOp->view());
+
+ if(iView)
+ iView->sort();
+ }
+ fileHighlighted(NULL);
+}
+
+void CKCmFontInst::addFonts()
+{
+ KURL::List list=KFileDialog::getOpenURLs(QString::null, "application/x-font-ttf application/x-font-otf "
+ "application/x-font-ttc application/x-font-type1 "
+ "application/x-font-pcf application/x-font-bdf",
+ //"application/x-font-snf application/x-font-speedo",
+ this, i18n("Add Fonts"));
+
+ if(list.count())
+ addFonts(list, itsDirOp->url());
+}
+
+void CKCmFontInst::removeFonts()
+{
+ if(itsDirOp->selectedItems()->isEmpty())
+ KMessageBox::information(this, i18n("You did not select anything to delete."), i18n("Nothing to Delete"));
+ else
+ {
+ KURL::List urls;
+ QStringList files;
+ KFileItemListIterator it(*(itsDirOp->selectedItems()));
+
+ for(; it.current(); ++it)
+ {
+ KURL url((*it)->url());
+
+ url.setQuery(KFI_KIO_NO_CLEAR);
+ files.append((*it)->text());
+ urls.append(url);
+ }
+
+ bool doIt=false;
+
+ switch(files.count())
+ {
+ case 0:
+ break;
+ case 1:
+ doIt = KMessageBox::Continue==KMessageBox::warningContinueCancel(this,
+ i18n("<qt>Do you really want to delete\n <b>'%1'</b>?</qt>").arg(files.first()),
+ i18n("Delete Font"), KStdGuiItem::del());
+ break;
+ default:
+ doIt = KMessageBox::Continue==KMessageBox::warningContinueCancelList(this,
+ i18n("Do you really want to delete this font?", "Do you really want to delete these %n fonts?",
+ files.count()),
+ files, i18n("Delete Fonts"), KStdGuiItem::del());
+ }
+
+ if(doIt)
+ {
+ KIO::DeleteJob *job = KIO::del(urls, false, true);
+ connect(job, SIGNAL(result(KIO::Job *)), this, SLOT(delResult(KIO::Job *)));
+ job->setWindow(this);
+ job->setAutoErrorHandlingEnabled(true, this);
+ }
+ }
+}
+
+void CKCmFontInst::configure()
+{
+ CSettingsDialog(this).exec();
+}
+
+void CKCmFontInst::print()
+{
+#ifdef HAVE_XFT
+ KFileItemList list;
+ bool ok=false;
+
+ for (KFileItem *item=itsDirOp->view()->firstFileItem(); item && !ok; item=itsDirOp->view()->nextItem(item))
+ if(Print::printable(item->mimetype()))
+ ok=true;
+
+ if(ok)
+ {
+ const KFileItemList *list=itsDirOp->selectedItems();
+ bool select=false;
+
+ if(list)
+ {
+ KFileItemList::Iterator it(list->begin()),
+ end(list->end());
+
+ for(; it!=end && !select; ++it)
+ if(Print::printable((*it)->mimetype()))
+ select=true;
+ }
+
+ CPrintDialog dlg(this);
+
+ itsConfig.setGroup(CFG_GROUP);
+ if(dlg.exec(select, itsConfig.readNumEntry(CFG_FONT_SIZE, 1)))
+ {
+ static const int constSizes[]={0, 12, 18, 24, 36, 48};
+
+ QStringList items;
+ QValueVector<int> sizes;
+ CFcEngine engine;
+
+ if(dlg.outputAll())
+ {
+ for (KFileItem *item=itsDirOp->view()->firstFileItem(); item; item=itsDirOp->view()->nextItem(item))
+ items.append(item->name());
+ }
+ else
+ {
+ KFileItemList::Iterator it(list->begin()),
+ end(list->end());
+
+ for(; it!=end; ++it)
+ items.append((*it)->name());
+ }
+ Print::printItems(items, constSizes[dlg.chosenSize()], this, engine);
+ itsConfig.writeEntry(CFG_FONT_SIZE, dlg.chosenSize());
+ if(itsEmbeddedAdmin)
+ itsConfig.sync();
+ }
+ }
+ else
+ KMessageBox::information(this, i18n("There are no printable fonts.\nYou can only print non-bitmap fonts."),
+ i18n("Cannot Print"));
+#endif
+}
+
+void CKCmFontInst::dropped(const KFileItem *i, QDropEvent *, const KURL::List &urls)
+{
+ if(urls.count())
+ addFonts(urls, i && i->isDir() ? i->url() : itsDirOp->url());
+}
+
+void CKCmFontInst::infoMessage(const QString &msg)
+{
+ itsStatusLabel->setText(msg);
+}
+
+static QString family(const QString &name)
+{
+ int commaPos=name.find(',');
+
+ return -1==commaPos ? name : name.left(commaPos);
+}
+
+void CKCmFontInst::updateInformation(int, int fonts)
+{
+ KIO::filesize_t size=0;
+ QString text(i18n("One Font", "%n Fonts", fonts));
+ QStringList families;
+
+ if(fonts>0)
+ {
+ KFileItem *item=NULL;
+
+ for (item=itsDirOp->view()->firstFileItem(); item; item=itsDirOp->view()->nextItem(item))
+ {
+ QString fam(family(item->text()));
+
+ size+=item->size();
+ if(-1==families.findIndex(fam))
+ families+=fam;
+ }
+ }
+
+ if(fonts>0)
+ {
+ text+=" ";
+ text+=i18n("(%1 Total)").arg(KIO::convertSize(size));
+ }
+ text+=" - ";
+ text+=i18n("One Family", "%n Families", families.count());
+ itsStatusLabel->setText(text);
+}
+
+void CKCmFontInst::delResult(KIO::Job *job)
+{
+ //
+ // To speed up font deletion, we dont rescan font list each time - so after this has completed, we need
+ // to refresh font list before updating the directory listing...
+ QByteArray packedArgs;
+ QDataStream stream(packedArgs, IO_WriteOnly);
+
+ stream << KFI::SPECIAL_RESCAN;
+
+ KIO::NetAccess::synchronousRun(KIO::special(KFI_KIO_FONTS_PROTOCOL ":/", packedArgs), this);
+ jobResult(job);
+}
+
+void CKCmFontInst::jobResult(KIO::Job *job)
+{
+ //
+ // Force an update of the view. For some reason the view is not automatically updated when
+ // run in embedded mode - e.g. from the "Admin" mode button on KControl.
+ itsDirOp->dirLister()->updateDirectory(itsDirOp->url());
+ if(job && 0==job->error())
+ KMessageBox::information(this,
+#ifdef HAVE_XFT
+ i18n("<p>Please note that any open applications will need to be restarted in order "
+ "for any changes to be noticed.<p><p>(You will also have to restart this application "
+ "in order to use its print function on any newly installed fonts.)</p>"),
+#else
+ i18n("Please note that any open applications will need to be restarted in order "
+ "for any changes to be noticed."),
+#endif
+ i18n("Success"), "KFontinst_WarnAboutFontChangesAndOpenApps");
+}
+
+void CKCmFontInst::addFonts(const KURL::List &src, const KURL &dest)
+{
+ if(src.count())
+ {
+ KURL::List copy(src);
+ KURL::List::ConstIterator it;
+
+ //
+ // Check if font has any associated AFM or PFM file...
+ for(it=src.begin(); it!=src.end(); ++it)
+ {
+ KURL::List associatedUrls;
+
+ Misc::getAssociatedUrls(*it, associatedUrls, false, this);
+ copy+=associatedUrls;
+ }
+
+ KIO::CopyJob *job=KIO::copy(copy, dest, true);
+ connect(job, SIGNAL(result(KIO::Job *)), this, SLOT(jobResult(KIO::Job *)));
+ job->setWindow(this);
+ job->setAutoErrorHandlingEnabled(true, this);
+ }
+}
+
+}
+
+#include "KCmFontInst.moc"
diff --git a/kcontrol/kfontinst/kcmfontinst/KCmFontInst.h b/kcontrol/kfontinst/kcmfontinst/KCmFontInst.h
new file mode 100644
index 000000000..add6c4c36
--- /dev/null
+++ b/kcontrol/kfontinst/kcmfontinst/KCmFontInst.h
@@ -0,0 +1,116 @@
+#ifndef __KCM_FONT_INST_H__
+#define __KCM_FONT_INST_H__
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : KFI::CKCmFontInst
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 26/04/2003
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2003, 2004
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <qstringlist.h>
+#include <kcmodule.h>
+#include <kurl.h>
+#include <kconfig.h>
+#include <kio/job.h>
+#ifdef HAVE_XFT
+#include <kparts/part.h>
+#endif
+
+class KDirOperator;
+class KAction;
+class KRadioAction;
+class KActionMenu;
+class KToggleAction;
+class KFileItem;
+class QLabel;
+class QSplitter;
+class QDropEvent;
+class KFileItem;
+
+namespace KFI
+{
+
+class CKCmFontInst : public KCModule
+{
+ Q_OBJECT
+
+ public:
+
+ CKCmFontInst(QWidget *parent=NULL, const char *name=NULL, const QStringList &list=QStringList());
+ virtual ~CKCmFontInst();
+
+ void setMimeTypes(bool showBitmap);
+
+ public slots:
+
+ void filterFonts();
+ QString quickHelp() const;
+ void listView();
+ void iconView();
+ void setupMenu();
+ void setupViewMenu();
+ void fileHighlighted(const KFileItem *item);
+ void loadingFinished();
+ void addFonts();
+ void removeFonts();
+ void configure();
+ void print();
+ void dropped(const KFileItem *i, QDropEvent *e, const KURL::List &urls);
+ void infoMessage(const QString &msg);
+ void updateInformation(int dirs, int fonts);
+ void delResult(KIO::Job *job);
+ void jobResult(KIO::Job *job);
+
+ private:
+
+ void addFonts(const KURL::List &src, const KURL &dest);
+
+ private:
+
+ KDirOperator *itsDirOp;
+ KURL itsTop;
+ KToggleAction *itsShowBitmapAct;
+ KAction *itsSepDirsAct,
+ *itsShowHiddenAct,
+ *itsDeleteAct;
+ KRadioAction *itsListAct,
+ *itsIconAct;
+ KActionMenu *itsViewMenuAct;
+#ifdef HAVE_XFT
+ KParts::ReadOnlyPart *itsPreview;
+#endif
+ QSplitter *itsSplitter;
+ KConfig itsConfig;
+ bool itsEmbeddedAdmin;
+ QLabel *itsStatusLabel;
+};
+
+}
+
+#endif
diff --git a/kcontrol/kfontinst/kcmfontinst/KFileFontIconView.cpp b/kcontrol/kfontinst/kcmfontinst/KFileFontIconView.cpp
new file mode 100644
index 000000000..d814d0c6b
--- /dev/null
+++ b/kcontrol/kfontinst/kcmfontinst/KFileFontIconView.cpp
@@ -0,0 +1,88 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : KFI::CKFileFontIconView
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 31/05/2003
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2003, 2004
+////////////////////////////////////////////////////////////////////////////////
+
+#include <qevent.h>
+#include <kfileitem.h>
+#include <kurldrag.h>
+#include "KFileFontIconView.h"
+
+namespace KFI
+{
+
+// CPD: KDE4 should make acceptDrag() virtual there fore can get rid of all these ::contentsX functions...
+void CKFileFontIconView::contentsDragEnterEvent(QDragEnterEvent *e)
+{
+ if(acceptDrag(e))
+ KFileIconView::contentsDragEnterEvent(e);
+ else
+ e->ignore();
+}
+
+void CKFileFontIconView::contentsDragMoveEvent(QDragMoveEvent *e)
+{
+ if(acceptDrag(e))
+ KFileIconView::contentsDragMoveEvent(e);
+ else
+ e->ignore();
+}
+
+void CKFileFontIconView::contentsDropEvent(QDropEvent *e)
+{
+ contentsDragLeaveEvent(NULL);
+
+ if(acceptDrag(e))
+ KFileIconView::contentsDropEvent(e);
+ else
+ e->ignore();
+}
+
+bool CKFileFontIconView::acceptDrag(QDropEvent *e) const
+{
+#if 0 // Crashes - seems to be called to quick???
+ bool ok=false;
+ KURL::List urls;
+
+ if(KURLDrag::canDecode(e) && (e->source()!=const_cast<CKFileFontIconView *>(this)) &&
+ (QDropEvent::Copy==e->action() || QDropEvent::Move==e->action()) &&
+ KURLDrag::decode(e, urls) && !urls.isEmpty())
+ {
+ KURL::List::Iterator it;
+
+ ok=true;
+ for(it=urls.begin(); ok && it!=urls.end(); ++it)
+ if(!CFontEngine::isAFontOrAfm(QFile::encodeName((*it).path())))
+ ok=false;
+ }
+
+ return ok;
+#endif
+ return KURLDrag::canDecode(e) && (e->source()!= const_cast<CKFileFontIconView*>(this)) &&
+ (QDropEvent::Copy==e->action() || QDropEvent::Move==e->action());
+}
+
+}
diff --git a/kcontrol/kfontinst/kcmfontinst/KFileFontIconView.h b/kcontrol/kfontinst/kcmfontinst/KFileFontIconView.h
new file mode 100644
index 000000000..936bb5bca
--- /dev/null
+++ b/kcontrol/kfontinst/kcmfontinst/KFileFontIconView.h
@@ -0,0 +1,55 @@
+#ifndef __KFILE_FONT_ICON_VIEW_H__
+#define __KFILE_FONT_ICON_VIEW_H__
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : KFI::CKFileFontIconView
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 01/08/2003
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2003, 2004
+////////////////////////////////////////////////////////////////////////////////
+
+#include <kfileiconview.h>
+
+namespace KFI
+{
+
+class CKFileFontIconView : public KFileIconView
+{
+ public:
+
+ CKFileFontIconView(QWidget *parent, const char *name) : KFileIconView(parent, name) {}
+ virtual ~CKFileFontIconView() {}
+
+ protected:
+
+ // DND support
+ void contentsDragEnterEvent(QDragEnterEvent *e);
+ void contentsDragMoveEvent(QDragMoveEvent *e);
+ void contentsDropEvent(QDropEvent *e);
+ bool acceptDrag(QDropEvent *e) const;
+};
+
+}
+
+#endif
diff --git a/kcontrol/kfontinst/kcmfontinst/KFileFontView.cpp b/kcontrol/kfontinst/kcmfontinst/KFileFontView.cpp
new file mode 100644
index 000000000..7346ca6c8
--- /dev/null
+++ b/kcontrol/kfontinst/kcmfontinst/KFileFontView.cpp
@@ -0,0 +1,645 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : CKFileFontView
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 31/05/2003
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2003
+////////////////////////////////////////////////////////////////////////////////
+
+//
+// NOTE: HEAVILY copied from kfiledetailview.cpp...
+//
+// Copyright (C) 1997 Stephan Kulow <coolo@kde.org>
+// 2000, 2001 Carsten Pfeiffer <pfeiffer@kde.org>
+//
+
+#include <qevent.h>
+#include <qkeycode.h>
+#include <qheader.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <kapplication.h>
+#include <kfileitem.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+#include <kicontheme.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+#include <kurldrag.h>
+#include "KFileFontView.h"
+
+#define COL_NAME 0
+#define COL_SIZE 1
+#define COL_TYPE 2
+
+class CKFileFontView::CKFileFontViewPrivate
+{
+ public:
+
+ CKFileFontViewPrivate() : itsDropItem(0) {}
+
+ CFontListViewItem *itsDropItem;
+ QTimer itsAutoOpenTimer;
+};
+
+CKFileFontView::CKFileFontView(QWidget *parent, const char *name)
+ : KListView(parent, name),
+ KFileView(),
+ d(new CKFileFontViewPrivate())
+{
+ itsSortingCol = COL_NAME;
+ itsBlockSortingSignal = false;
+ setViewName(i18n("Detailed View"));
+
+ addColumn(i18n("Name"));
+ addColumn(i18n("Size"));
+ addColumn(i18n("Type"));
+ setShowSortIndicator(true);
+ setAllColumnsShowFocus(true);
+ setDragEnabled(false);
+
+ connect(header(), SIGNAL(sectionClicked(int)), SLOT(slotSortingChanged(int)));
+ connect(this, SIGNAL(returnPressed(QListViewItem *)), SLOT(slotActivate(QListViewItem *)));
+ connect(this, SIGNAL(clicked(QListViewItem *, const QPoint&, int)), SLOT(selected( QListViewItem *)));
+ connect(this, SIGNAL(doubleClicked(QListViewItem *, const QPoint &, int)), SLOT(slotActivate(QListViewItem *)));
+ connect(this, SIGNAL(contextMenuRequested(QListViewItem *, const QPoint &, int)),
+ this, SLOT(slotActivateMenu(QListViewItem *, const QPoint &)));
+
+ // DND
+ connect(&(d->itsAutoOpenTimer), SIGNAL(timeout()), this, SLOT(slotAutoOpen()));
+ setSelectionMode(KFileView::selectionMode());
+ itsResolver = new KMimeTypeResolver<CFontListViewItem, CKFileFontView>(this);
+}
+
+CKFileFontView::~CKFileFontView()
+{
+ delete itsResolver;
+ delete d;
+}
+
+void CKFileFontView::setSelected(const KFileItem *info, bool enable)
+{
+ if (info)
+ {
+ // we can only hope that this casts works
+ CFontListViewItem *item = (CFontListViewItem*)info->extraData(this);
+
+ if (item)
+ KListView::setSelected(item, enable);
+ }
+}
+
+void CKFileFontView::setCurrentItem(const KFileItem *item)
+{
+ if (item)
+ {
+ CFontListViewItem *it = (CFontListViewItem*) item->extraData(this);
+
+ if (it)
+ KListView::setCurrentItem(it);
+ }
+}
+
+KFileItem * CKFileFontView::currentFileItem() const
+{
+ CFontListViewItem *current = static_cast<CFontListViewItem*>(currentItem());
+
+ return current ? current->fileInfo() : NULL;
+}
+
+void CKFileFontView::clearSelection()
+{
+ KListView::clearSelection();
+}
+
+void CKFileFontView::selectAll()
+{
+ if (KFile::NoSelection!=KFileView::selectionMode() && KFile::Single!=KFileView::selectionMode())
+ KListView::selectAll(true);
+}
+
+void CKFileFontView::invertSelection()
+{
+ KListView::invertSelection();
+}
+
+void CKFileFontView::slotActivateMenu(QListViewItem *item,const QPoint& pos)
+{
+ if (!item)
+ sig->activateMenu(0, pos);
+ else
+ {
+ CFontListViewItem *i = (CFontListViewItem*) item;
+ sig->activateMenu(i->fileInfo(), pos);
+ }
+}
+
+void CKFileFontView::clearView()
+{
+ itsResolver->m_lstPendingMimeIconItems.clear();
+ KListView::clear();
+}
+
+void CKFileFontView::insertItem(KFileItem *i)
+{
+ KFileView::insertItem(i);
+
+ CFontListViewItem *item = new CFontListViewItem((QListView*) this, i);
+
+ setSortingKey(item, i);
+
+ i->setExtraData(this, item);
+
+ if (!i->isMimeTypeKnown())
+ itsResolver->m_lstPendingMimeIconItems.append(item);
+}
+
+void CKFileFontView::slotActivate(QListViewItem *item)
+{
+ if (item)
+ {
+ const KFileItem *fi = ((CFontListViewItem*)item)->fileInfo();
+
+ if (fi)
+ sig->activate(fi);
+ }
+}
+
+void CKFileFontView::selected(QListViewItem *item)
+{
+ if (item && !(KApplication::keyboardMouseState() & (ShiftButton|ControlButton)) &&
+ KGlobalSettings::singleClick())
+ {
+ const KFileItem *fi = ((CFontListViewItem*)item)->fileInfo();
+
+ if (fi && (fi->isDir() || !onlyDoubleClickSelectsFiles()))
+ sig->activate(fi);
+ }
+}
+
+void CKFileFontView::highlighted( QListViewItem *item )
+{
+ if (item)
+ {
+ const KFileItem *fi = ((CFontListViewItem*)item)->fileInfo();
+
+ if (fi)
+ sig->highlightFile(fi);
+ }
+}
+
+void CKFileFontView::setSelectionMode(KFile::SelectionMode sm)
+{
+ disconnect(SIGNAL(selectionChanged()), this);
+ disconnect(SIGNAL(selectionChanged(QListViewItem *)), this);
+
+ switch (sm)
+ {
+ case KFile::Multi:
+ QListView::setSelectionMode(QListView::Multi);
+ break;
+ case KFile::Extended:
+ QListView::setSelectionMode(QListView::Extended);
+ break;
+ case KFile::NoSelection:
+ QListView::setSelectionMode(QListView::NoSelection);
+ break;
+ default: // fall through
+ case KFile::Single:
+ QListView::setSelectionMode(QListView::Single);
+ break;
+ }
+
+ // for highlighting
+ if (KFile::Multi==sm || KFile::Extended==sm)
+ connect(this, SIGNAL(selectionChanged()), SLOT(slotSelectionChanged()));
+ else
+ connect(this, SIGNAL(selectionChanged(QListViewItem *)), SLOT(highlighted(QListViewItem * )));
+}
+
+bool CKFileFontView::isSelected(const KFileItem *i) const
+{
+ if (!i)
+ return false;
+ else
+ {
+ CFontListViewItem *item = (CFontListViewItem*) i->extraData(this);
+
+ return (item && item->isSelected());
+ }
+}
+
+void CKFileFontView::updateView(bool b)
+{
+ if (b)
+ {
+ QListViewItemIterator it((QListView*)this);
+
+ for (; it.current(); ++it)
+ {
+ CFontListViewItem *item=static_cast<CFontListViewItem *>(it.current());
+
+ item->setPixmap(0, item->fileInfo()->pixmap(KIcon::SizeSmall));
+ }
+ }
+}
+
+void CKFileFontView::updateView(const KFileItem *i)
+{
+ if (i)
+ {
+ CFontListViewItem *item = (CFontListViewItem*) i->extraData(this);
+
+ if (item)
+ {
+ item->init();
+ setSortingKey(item, i);
+ }
+ }
+}
+
+void CKFileFontView::setSortingKey(CFontListViewItem *item, const KFileItem *i)
+{
+ QDir::SortSpec spec = KFileView::sorting();
+
+ if (spec&QDir::Size)
+ item->setKey(sortingKey(i->size(), i->isDir(), spec));
+ else
+ item->setKey(sortingKey(i->text(), i->isDir(), spec));
+}
+
+void CKFileFontView::removeItem(const KFileItem *i)
+{
+ if (i)
+ {
+ CFontListViewItem *item = (CFontListViewItem*) i->extraData(this);
+
+ itsResolver->m_lstPendingMimeIconItems.remove(item);
+ delete item;
+
+ KFileView::removeItem(i);
+ }
+}
+
+void CKFileFontView::slotSortingChanged(int col)
+{
+ QDir::SortSpec sort = sorting();
+ int sortSpec = -1;
+ bool reversed = col == itsSortingCol && (sort & QDir::Reversed) == 0;
+ itsSortingCol = col;
+
+ switch(col)
+ {
+ case COL_NAME:
+ sortSpec = (sort & ~QDir::SortByMask | QDir::Name);
+ break;
+ case COL_SIZE:
+ sortSpec = (sort & ~QDir::SortByMask | QDir::Size);
+ break;
+ // the following columns have no equivalent in QDir, so we set it
+ // to QDir::Unsorted and remember the column (itsSortingCol)
+ case COL_TYPE:
+ sortSpec = (sort & ~QDir::SortByMask | QDir::Time);
+ break;
+ default:
+ break;
+ }
+
+ if (reversed)
+ sortSpec|=QDir::Reversed;
+ else
+ sortSpec&=~QDir::Reversed;
+
+ if (sort & QDir::IgnoreCase)
+ sortSpec|=QDir::IgnoreCase;
+ else
+ sortSpec&=~QDir::IgnoreCase;
+
+ KFileView::setSorting(static_cast<QDir::SortSpec>(sortSpec));
+
+ KFileItem *item;
+ KFileItemListIterator it(*items());
+
+ if ( sortSpec & QDir::Size )
+ {
+ for (; (item = it.current()); ++it )
+ {
+ CFontListViewItem *i = viewItem(item);
+ i->setKey(sortingKey(item->size(), item->isDir(), sortSpec));
+ }
+ }
+ else
+ for (; (item = it.current()); ++it )
+ {
+ CFontListViewItem *i = viewItem(item);
+
+ i->setKey(sortingKey(i->text(itsSortingCol), item->isDir(), sortSpec));
+ }
+
+ KListView::setSorting(itsSortingCol, !reversed);
+ KListView::sort();
+
+ if (!itsBlockSortingSignal)
+ sig->changeSorting( static_cast<QDir::SortSpec>( sortSpec ) );
+}
+
+void CKFileFontView::setSorting(QDir::SortSpec spec)
+{
+ if (spec & QDir::Size)
+ itsSortingCol=COL_SIZE;
+ else
+ itsSortingCol=COL_NAME;
+
+ // inversed, because slotSortingChanged will reverse it
+ if (spec & QDir::Reversed)
+ spec = (QDir::SortSpec) (spec & ~QDir::Reversed);
+ else
+ spec = (QDir::SortSpec) (spec | QDir::Reversed);
+
+ KFileView::setSorting((QDir::SortSpec) spec);
+
+ // don't emit sortingChanged() when called via setSorting()
+ itsBlockSortingSignal = true; // can't use blockSignals()
+ slotSortingChanged(itsSortingCol);
+ itsBlockSortingSignal = false;
+}
+
+void CKFileFontView::ensureItemVisible(const KFileItem *i)
+{
+ if (i)
+ {
+ CFontListViewItem *item = (CFontListViewItem*) i->extraData(this);
+
+ if ( item )
+ KListView::ensureItemVisible(item);
+ }
+}
+
+// we're in multiselection mode
+void CKFileFontView::slotSelectionChanged()
+{
+ sig->highlightFile(NULL);
+}
+
+KFileItem * CKFileFontView::firstFileItem() const
+{
+ CFontListViewItem *item = static_cast<CFontListViewItem*>(firstChild());
+
+ return item ? item->fileInfo() : NULL;
+}
+
+KFileItem * CKFileFontView::nextItem(const KFileItem *fileItem) const
+{
+ if (fileItem)
+ {
+ CFontListViewItem *item = viewItem(fileItem);
+
+ return item && item->itemBelow() ? ((CFontListViewItem*) item->itemBelow())->fileInfo() : NULL;
+ }
+
+ return firstFileItem();
+}
+
+KFileItem * CKFileFontView::prevItem(const KFileItem *fileItem) const
+{
+ if (fileItem)
+ {
+ CFontListViewItem *item = viewItem(fileItem);
+
+ return item && item->itemAbove() ? ((CFontListViewItem*) item->itemAbove())->fileInfo() : NULL;
+ }
+
+ return firstFileItem();
+}
+
+void CKFileFontView::keyPressEvent(QKeyEvent *e)
+{
+ KListView::keyPressEvent(e);
+
+ if (Key_Return==e->key() || Key_Enter==e->key())
+ if (e->state() & ControlButton)
+ e->ignore();
+ else
+ e->accept();
+}
+
+//
+// mimetype determination on demand
+//
+void CKFileFontView::mimeTypeDeterminationFinished()
+{
+ // anything to do?
+}
+
+void CKFileFontView::determineIcon(CFontListViewItem *item)
+{
+ item->fileInfo()->determineMimeType();
+ updateView(item->fileInfo());
+}
+
+void CKFileFontView::listingCompleted()
+{
+ itsResolver->start();
+}
+
+QDragObject *CKFileFontView::dragObject()
+{
+ // create a list of the URL:s that we want to drag
+ KURL::List urls;
+ KFileItemListIterator it(* KFileView::selectedItems());
+ QPixmap pixmap;
+ QPoint hotspot;
+
+ for ( ; it.current(); ++it )
+ urls.append( (*it)->url() );
+
+ if(urls.count()> 1)
+ pixmap = DesktopIcon("kmultiple", KIcon::SizeSmall);
+ if(pixmap.isNull())
+ pixmap = currentFileItem()->pixmap(KIcon::SizeSmall);
+
+ hotspot.setX(pixmap.width() / 2);
+ hotspot.setY(pixmap.height() / 2);
+
+ QDragObject *dragObject=new KURLDrag(urls, widget());
+
+ if(dragObject)
+ dragObject->setPixmap(pixmap, hotspot);
+
+ return dragObject;
+}
+
+void CKFileFontView::slotAutoOpen()
+{
+ d->itsAutoOpenTimer.stop();
+
+ if(d->itsDropItem)
+ {
+ KFileItem *fileItem = d->itsDropItem->fileInfo();
+
+ if (fileItem && !fileItem->isFile() && (fileItem->isDir() || fileItem->isLink()))
+ sig->activate(fileItem);
+ }
+}
+
+bool CKFileFontView::acceptDrag(QDropEvent *e) const
+{
+#if 0 // Following doesn't seem to work, why???
+ bool ok=false;
+ KURL::List urls;
+
+
+ if((e->source()!=const_cast<CKFileFontView *>(this)) &&
+ (QDropEvent::Copy==e->action() || QDropEvent::Move==e->action()) &&
+ KURLDrag::decode(e, urls) && !urls.isEmpty())
+ {
+ KURL::List::Iterator it;
+
+ ok=true;
+ for(it=urls.begin(); ok && it!=urls.end(); ++it)
+ if(!CFontEngine::isAFontOrAfm(QFile::encodeName((*it).path())))
+ ok=false;
+ }
+
+ return ok;
+#endif
+
+ return KURLDrag::canDecode(e) && (e->source()!= const_cast<CKFileFontView*>(this)) &&
+ (QDropEvent::Copy==e->action() || QDropEvent::Move==e->action());
+}
+
+void CKFileFontView::contentsDragEnterEvent(QDragEnterEvent *e)
+{
+ if (!acceptDrag(e)) // can we decode this ?
+ e->ignore(); // No
+ else
+ {
+ e->acceptAction(); // Yes
+
+ if((dropOptions() & AutoOpenDirs))
+ {
+ CFontListViewItem *item = dynamic_cast<CFontListViewItem*>(itemAt(contentsToViewport(e->pos())));
+ if (item) // are we over an item ?
+ {
+ d->itsDropItem = item;
+ d->itsAutoOpenTimer.start(autoOpenDelay()); // restart timer
+ }
+ else
+ {
+ d->itsDropItem = 0;
+ d->itsAutoOpenTimer.stop();
+ }
+ }
+ }
+}
+
+void CKFileFontView::contentsDragMoveEvent(QDragMoveEvent *e)
+{
+ if (!acceptDrag(e)) // can we decode this ?
+ e->ignore(); // No
+ else
+ {
+ e->acceptAction(); // Yes
+
+ if ((dropOptions() & AutoOpenDirs))
+ {
+ CFontListViewItem *item = dynamic_cast<CFontListViewItem*>(itemAt(contentsToViewport(e->pos())));
+
+ if (item) // are we over an item ?
+ {
+ if (d->itsDropItem != item)
+ {
+ d->itsDropItem = item;
+ d->itsAutoOpenTimer.start(autoOpenDelay()); // restart timer
+ }
+ }
+ else
+ {
+ d->itsDropItem = 0;
+ d->itsAutoOpenTimer.stop();
+ }
+ }
+ }
+}
+
+void CKFileFontView::contentsDragLeaveEvent(QDragLeaveEvent *)
+{
+ d->itsDropItem = 0;
+ d->itsAutoOpenTimer.stop();
+}
+
+void CKFileFontView::contentsDropEvent(QDropEvent *e)
+{
+ d->itsDropItem = 0;
+ d->itsAutoOpenTimer.stop();
+
+ if (!acceptDrag(e)) // can we decode this ?
+ e->ignore(); // No
+ else
+ {
+ e->acceptAction(); // Yes
+
+ CFontListViewItem *item = dynamic_cast<CFontListViewItem*>(itemAt(contentsToViewport(e->pos())));
+ KFileItem *fileItem = item ? item->fileInfo() : 0;
+ KURL::List urls;
+
+ emit dropped(e, fileItem);
+
+ if(KURLDrag::decode(e, urls) && !urls.isEmpty())
+ {
+ emit dropped(e, urls, fileItem ? fileItem->url() : KURL());
+ sig->dropURLs(fileItem, e, urls);
+ }
+ }
+}
+
+void CKFileFontView::readConfig(KConfig *kc, const QString &group)
+{
+ restoreLayout(kc, group.isEmpty() ? QString("CFileFontView") : group);
+ slotSortingChanged(sortColumn());
+}
+
+void CKFileFontView::writeConfig(KConfig *kc, const QString &group)
+{
+ saveLayout(kc, group.isEmpty() ? QString("CFileFontView") : group);
+}
+
+/////////////////////////////////////////////////////////////////
+
+void CFontListViewItem::init()
+{
+ CFontListViewItem::setPixmap(COL_NAME, itsInf->pixmap(KIcon::SizeSmall));
+
+ setText(COL_NAME, itsInf->text());
+ setText(COL_SIZE, itsInf->isDir() ? "" : KGlobal::locale()->formatNumber(itsInf->size(), 0));
+ setText(COL_TYPE, itsInf->mimeComment());
+}
+
+void CKFileFontView::virtual_hook(int id, void *data)
+{
+ KListView::virtual_hook(id, data);
+ KFileView::virtual_hook(id, data);
+}
+
+#include "KFileFontView.moc"
diff --git a/kcontrol/kfontinst/kcmfontinst/KFileFontView.h b/kcontrol/kfontinst/kcmfontinst/KFileFontView.h
new file mode 100644
index 000000000..a58f9d908
--- /dev/null
+++ b/kcontrol/kfontinst/kcmfontinst/KFileFontView.h
@@ -0,0 +1,219 @@
+#ifndef __KFILE_FONT_VIEW_H__
+#define __KFILE_FONT_VIEW_H__
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : CKFileFontView
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 31/05/2003
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2003
+////////////////////////////////////////////////////////////////////////////////
+
+//
+// NOTE: HEAVILY copied from kfiledetailview.cpp...
+//
+// Copyright (C) 1997 Stephan Kulow <coolo@kde.org>
+// 2000, 2001 Carste
+
+class KFileItem;
+class QWidget;
+class QKeyEvent;
+
+#include <klistview.h>
+#include <kmimetyperesolver.h>
+
+#include "kfileview.h"
+
+/**
+ * An item for the listiew, that has a reference to its corresponding
+ * @ref KFileItem.
+ */
+class CFontListViewItem : public KListViewItem
+{
+ public:
+
+ CFontListViewItem(QListView *parent, const QString &text, const QPixmap &icon, KFileItem *fi)
+ : KListViewItem(parent, text),
+ itsInf(fi)
+ {
+ setPixmap(0, icon);
+ setText(0, text);
+ }
+
+ CFontListViewItem(QListView *parent, KFileItem *fi)
+ : KListViewItem(parent),
+ itsInf(fi)
+ {
+ init();
+ }
+
+ CFontListViewItem(QListView *parent, const QString &text, const QPixmap &icon, KFileItem *fi, QListViewItem *after)
+ : KListViewItem(parent, after),
+ itsInf(fi)
+ {
+ setPixmap(0, icon);
+ setText(0, text);
+ }
+
+ ~CFontListViewItem() { itsInf->removeExtraData(listView()); }
+
+ /**
+ * @returns the corresponding KFileItem
+ */
+ KFileItem *fileInfo() const { return itsInf; }
+
+ virtual QString key( int /*column*/, bool /*ascending*/ ) const { return itsKey; }
+
+ void setKey( const QString& key ) { itsKey = key; }
+
+ QRect rect() const
+ {
+ QRect r = listView()->itemRect(this);
+
+ return QRect(listView()->viewportToContents(r.topLeft()), QSize(r.width(), r.height()));
+ }
+
+ void init();
+
+ private:
+
+ KFileItem *itsInf;
+ QString itsKey;
+
+ class CFontListViewItemPrivate;
+
+ CFontListViewItemPrivate *d;
+};
+
+/**
+ * A list-view capable of showing @ref KFileItem'. Used in the filedialog
+ * for example. Most of the documentation is in @ref KFileView class.
+ *
+ * @see KDirOperator
+ * @see KCombiView
+ * @see KFileIconView
+ */
+class CKFileFontView : public KListView, public KFileView
+{
+ Q_OBJECT
+
+ public:
+
+ CKFileFontView(QWidget *parent, const char *name);
+ virtual ~CKFileFontView();
+
+ virtual QWidget * widget() { return this; }
+ virtual void clearView();
+ virtual void setAutoUpdate(bool) {} // ### unused. remove in KDE4
+ virtual void setSelectionMode( KFile::SelectionMode sm );
+ virtual void updateView(bool b);
+ virtual void updateView(const KFileItem *i);
+ virtual void removeItem(const KFileItem *i);
+ virtual void listingCompleted();
+ virtual void setSelected(const KFileItem *i, bool b);
+ virtual bool isSelected(const KFileItem *i) const;
+ virtual void clearSelection();
+ virtual void selectAll();
+ virtual void invertSelection();
+ virtual void setCurrentItem( const KFileItem *i);
+ virtual KFileItem * currentFileItem() const;
+ virtual KFileItem * firstFileItem() const;
+ virtual KFileItem * nextItem(const KFileItem *i) const;
+ virtual KFileItem * prevItem(const KFileItem *i) const;
+ virtual void insertItem( KFileItem *i);
+
+ void readConfig(KConfig *kc, const QString &group);
+ void writeConfig(KConfig *kc, const QString &group);
+
+ // implemented to get noticed about sorting changes (for sortingIndicator)
+ virtual void setSorting(QDir::SortSpec s);
+ void ensureItemVisible(const KFileItem *i);
+
+ // for KMimeTypeResolver
+ void mimeTypeDeterminationFinished();
+ void determineIcon(CFontListViewItem *item);
+ QScrollView * scrollWidget() const { return (QScrollView*) this; }
+
+ signals:
+ // The user dropped something.
+ // fileItem points to the item dropped on or can be 0 if the
+ // user dropped on empty space.
+ void dropped(QDropEvent *event, KFileItem *fileItem);
+ // The user dropped the URLs urls.
+ // url points to the item dropped on or can be empty if the
+ // user dropped on empty space.
+ void dropped(QDropEvent *event, const KURL::List &urls, const KURL &url);
+
+ protected:
+
+ virtual void keyPressEvent(QKeyEvent *e);
+ // DND support
+ QDragObject * dragObject();
+ void contentsDragEnterEvent(QDragEnterEvent *e);
+ void contentsDragMoveEvent(QDragMoveEvent *e);
+ void contentsDragLeaveEvent(QDragLeaveEvent *e);
+ void contentsDropEvent(QDropEvent *e);
+ bool acceptDrag(QDropEvent *e) const;
+
+ int itsSortingCol;
+
+ protected slots:
+
+ void slotSelectionChanged();
+
+ private slots:
+
+ void slotSortingChanged(int c);
+ void selected(QListViewItem *item);
+ void slotActivate(QListViewItem *item);
+ void highlighted(QListViewItem *item);
+ void slotActivateMenu(QListViewItem *item, const QPoint& pos);
+ void slotAutoOpen();
+
+ private:
+
+ virtual void insertItem(QListViewItem *i) { KListView::insertItem(i); }
+ virtual void setSorting(int i, bool b) { KListView::setSorting(i, b); }
+ virtual void setSelected(QListViewItem *i, bool b) { KListView::setSelected(i, b); }
+
+ inline CFontListViewItem * viewItem( const KFileItem *item ) const
+ {
+ return item ? (CFontListViewItem *) item->extraData(this) : NULL;
+ }
+
+ void setSortingKey( CFontListViewItem *item, const KFileItem *i);
+
+ bool itsBlockSortingSignal;
+ KMimeTypeResolver<CFontListViewItem,CKFileFontView> *itsResolver;
+
+ protected:
+
+ virtual void virtual_hook(int id, void *data);
+
+ private:
+
+ class CKFileFontViewPrivate;
+ CKFileFontViewPrivate *d;
+};
+
+#endif
diff --git a/kcontrol/kfontinst/kcmfontinst/Makefile.am b/kcontrol/kfontinst/kcmfontinst/Makefile.am
new file mode 100644
index 000000000..7a4c78920
--- /dev/null
+++ b/kcontrol/kfontinst/kcmfontinst/Makefile.am
@@ -0,0 +1,31 @@
+if include_fontinst_tn
+FONTINST_PRINT_INC=-I$(srcdir)/../viewpart
+FONTINST_PRINT_LIB=../viewpart/libkfontinstprint.la
+endif
+
+kde_module_LTLIBRARIES = kcm_fontinst.la
+kcm_fontinst_la_LIBADD = $(LIB_KIO) $(FONTINST_PRINT_LIB) $(LIBFREETYPE_LIBS) $(LIBFONTCONFIG_LIBS) ../lib/libkfontinst.la
+METASOURCES = AUTO
+kcm_fontinst_la_LDFLAGS = $(KDE_PLUGIN) $(all_libraries) $(KDE_RPATH) -module -avoid-version -no-undefined
+AM_CPPFLAGS = -I$(srcdir)/../lib $(FONTINST_PRINT_INC) -I$(srcdir)/../../fonts $(all_includes) $(LIBFREETYPE_CFLAGS) $(LIBFONTCONFIG_CFLAGS)
+
+xdg_apps_DATA = kcmfontinst.desktop
+
+kcm_fontinst_la_SOURCES = \
+ KCmFontInst.cpp \
+ KFileFontIconView.cpp \
+ KFileFontView.cpp \
+ PrintDialog.cpp \
+ SettingsDialog.cpp
+
+EXTRA_DIST = \
+ $(xdg_apps_DATA) \
+ KCmFontInst.h \
+ KFileFontIconView.h \
+ KFileFontView.h \
+ PrintDialog.h \
+ SettingsDialog.h
+
+noinst_HEADERS = $(EXTRA_DIST)
+
+KDE_ICON = AUTO
diff --git a/kcontrol/kfontinst/kcmfontinst/PrintDialog.cpp b/kcontrol/kfontinst/kcmfontinst/PrintDialog.cpp
new file mode 100644
index 000000000..e902fa1e1
--- /dev/null
+++ b/kcontrol/kfontinst/kcmfontinst/PrintDialog.cpp
@@ -0,0 +1,74 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : KFI::CPrintDialog
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 12/05/2005
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2005
+////////////////////////////////////////////////////////////////////////////////
+
+#include "PrintDialog.h"
+#include <qlayout.h>
+#include <qframe.h>
+#include <qlabel.h>
+#include <klocale.h>
+
+namespace KFI
+{
+
+CPrintDialog::CPrintDialog(QWidget *parent)
+ : KDialogBase(Plain, i18n("Print Font Samples"), Ok|Cancel, Ok, parent, NULL, true, false)
+{
+ QFrame *page=plainPage();
+ QGridLayout *layout=new QGridLayout(page, 1, 1, 0, spacingHint());
+
+ layout->addWidget(new QLabel(i18n("Output:"), page), 0, 0);
+ itsOutput=new QComboBox(page);
+ itsOutput->insertItem(i18n("All Fonts"), 0);
+ itsOutput->insertItem(i18n("Selected Fonts"), 1);
+ layout->addWidget(itsOutput, 0, 1);
+ layout->addWidget(new QLabel(i18n("Font size:"), page), 1, 0);
+ itsSize=new QComboBox(page);
+ itsSize->insertItem(i18n("Waterfall"), 0);
+ itsSize->insertItem(i18n("12pt"), 1);
+ itsSize->insertItem(i18n("18pt"), 2);
+ itsSize->insertItem(i18n("24pt"), 3);
+ itsSize->insertItem(i18n("36pt"), 4);
+ itsSize->insertItem(i18n("48pt"), 5);
+ layout->addWidget(itsSize, 1, 1);
+ layout->addItem(new QSpacerItem(2, 2), 2, 1);
+}
+
+bool CPrintDialog::exec(bool select, int size)
+{
+ if(!select)
+ {
+ itsOutput->setCurrentItem(0);
+ itsOutput->setEnabled(false);
+ }
+ else
+ itsOutput->setCurrentItem(1);
+ itsSize->setCurrentItem(size);
+ return QDialog::Accepted==QDialog::exec();
+}
+
+}
diff --git a/kcontrol/kfontinst/kcmfontinst/PrintDialog.h b/kcontrol/kfontinst/kcmfontinst/PrintDialog.h
new file mode 100644
index 000000000..9be67f6d4
--- /dev/null
+++ b/kcontrol/kfontinst/kcmfontinst/PrintDialog.h
@@ -0,0 +1,56 @@
+#ifndef __PRINT_DIALOG_H__
+#define __PRINT_DIALOG_H__
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : KFI::CPrintDialog
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 12/05/2005
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2005
+////////////////////////////////////////////////////////////////////////////////
+
+#include <kdialogbase.h>
+#include <qcombobox.h>
+
+namespace KFI
+{
+
+class CPrintDialog : public KDialogBase
+{
+ public:
+
+ CPrintDialog(QWidget *parent);
+
+ bool exec(bool select, int size);
+ int chosenSize() { return itsSize->currentItem(); }
+ bool outputAll() { return 0==itsOutput->currentItem(); }
+
+ private:
+
+ QComboBox *itsOutput,
+ *itsSize;
+};
+
+}
+
+#endif
diff --git a/kcontrol/kfontinst/kcmfontinst/SettingsDialog.cpp b/kcontrol/kfontinst/kcmfontinst/SettingsDialog.cpp
new file mode 100644
index 000000000..255fca709
--- /dev/null
+++ b/kcontrol/kfontinst/kcmfontinst/SettingsDialog.cpp
@@ -0,0 +1,99 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : KFI::CSettingsDialog
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 10/05/2005
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2005
+////////////////////////////////////////////////////////////////////////////////
+
+#include "SettingsDialog.h"
+#include "KfiConstants.h"
+#include "Misc.h"
+#include <qlayout.h>
+#include <qcheckbox.h>
+#include <qvbox.h>
+#include <qwhatsthis.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kmessagebox.h>
+#include <kio/job.h>
+#include <kio/netaccess.h>
+
+namespace KFI
+{
+
+CSettingsDialog::CSettingsDialog(QWidget *parent)
+ : KDialogBase(parent, "settingsdialog", true, i18n("Settings"),
+ KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok, true)
+{
+ QVBox *page = makeVBoxMainWidget();
+
+ itsDoX=new QCheckBox(i18n("Configure fonts for legacy X applications"), page);
+ QWhatsThis::add(itsDoX, i18n("<p>Modern applications use a system called \"FontConfig\" to obtain the list of fonts. "
+ "Older applications, such as OpenOffice 1.x, GIMP 1.x, etc. use the previous \"core X fonts\" mechanism for "
+ "this.</p><p>Selecting this option will inform the installer to create the necessary files so that these "
+ "older applications can use the fonts you install.</p><p>Please note, however, that this will slow down "
+ "the installation process.<p>"));
+ itsDoGs=new QCheckBox(i18n("Configure fonts for Ghostscript"), page);
+ QWhatsThis::add(itsDoGs, i18n("<p>When printing, most applications create what is know as PostScript. This is then sent to a special "
+ "application, named Ghostscript, which can interpret the PostScript and send the appropriate instructions "
+ "to your printer. If your application does not embed whatever fonts it uses into the PostScript, then "
+ "Ghostscript needs to be informed as to which fonts you have installed, and where they are located.</p>"
+ "<p>Selecting this option will create the necessary Ghostscript config files.</p><p>Please note, however, "
+ "that this will also slow down the installation process.</p><p>As most applications can, and do, embed "
+ "the fonts into the PostScript before sending this to Ghostscript, this option can safely be disabled."));
+
+ KConfig cfg(Misc::root() ? KFI_ROOT_CFG_FILE : KFI_CFG_FILE);
+
+ itsDoX->setChecked(cfg.readBoolEntry(KFI_CFG_X_KEY, KFI_DEFAULT_CFG_X));
+ itsDoGs->setChecked(cfg.readBoolEntry(KFI_CFG_GS_KEY, KFI_DEFAULT_CFG_GS));
+}
+
+void CSettingsDialog::slotOk()
+{
+ KConfig cfg(Misc::root() ? KFI_ROOT_CFG_FILE : KFI_CFG_FILE);
+
+ bool oldDoX=cfg.readBoolEntry(KFI_CFG_X_KEY, KFI_DEFAULT_CFG_X),
+ oldDoGs=cfg.readBoolEntry(KFI_CFG_GS_KEY, KFI_DEFAULT_CFG_GS);
+
+ cfg.writeEntry(KFI_CFG_X_KEY, itsDoX->isChecked());
+ cfg.writeEntry(KFI_CFG_GS_KEY, itsDoGs->isChecked());
+ cfg.sync();
+
+ if( ((!oldDoX && itsDoX->isChecked()) || (!oldDoGs && itsDoGs->isChecked())) &&
+ KMessageBox::Yes==KMessageBox::questionYesNo(this, i18n("You have enabled a previously disabled option. Would you like the config "
+ "files updated now? (Normally they are only updated upon installing, or "
+ "removing, a font.)"), QString::null, i18n("Update"),i18n("Do Not Update")))
+ {
+ QByteArray packedArgs;
+ QDataStream stream(packedArgs, IO_WriteOnly);
+
+ stream << KFI::SPECIAL_RECONFIG;
+
+ KIO::NetAccess::synchronousRun(KIO::special(KFI_KIO_FONTS_PROTOCOL ":/", packedArgs), this);
+ }
+
+ hide();
+}
+
+}
diff --git a/kcontrol/kfontinst/kcmfontinst/SettingsDialog.h b/kcontrol/kfontinst/kcmfontinst/SettingsDialog.h
new file mode 100644
index 000000000..b41820e38
--- /dev/null
+++ b/kcontrol/kfontinst/kcmfontinst/SettingsDialog.h
@@ -0,0 +1,57 @@
+#ifndef __SETTINGS_DIALOG_H__
+#define __SETTINGS_DIALOG_H__
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : KFI::CSettingsDialog
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 10/05/2005
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2005
+////////////////////////////////////////////////////////////////////////////////
+
+#include <kdialogbase.h>
+
+class QCheckBox;
+
+namespace KFI
+{
+
+class CSettingsDialog : public KDialogBase
+{
+ public:
+
+ CSettingsDialog(QWidget *parent);
+
+ private slots:
+
+ void slotOk();
+
+ private:
+
+ QCheckBox *itsDoX,
+ *itsDoGs;
+};
+
+}
+
+#endif
diff --git a/kcontrol/kfontinst/kcmfontinst/cr16-action-newfont.png b/kcontrol/kfontinst/kcmfontinst/cr16-action-newfont.png
new file mode 100644
index 000000000..61eef357e
--- /dev/null
+++ b/kcontrol/kfontinst/kcmfontinst/cr16-action-newfont.png
Binary files differ
diff --git a/kcontrol/kfontinst/kcmfontinst/cr22-action-newfont.png b/kcontrol/kfontinst/kcmfontinst/cr22-action-newfont.png
new file mode 100644
index 000000000..049197a35
--- /dev/null
+++ b/kcontrol/kfontinst/kcmfontinst/cr22-action-newfont.png
Binary files differ
diff --git a/kcontrol/kfontinst/kcmfontinst/cr32-action-newfont.png b/kcontrol/kfontinst/kcmfontinst/cr32-action-newfont.png
new file mode 100644
index 000000000..9cd3d57bc
--- /dev/null
+++ b/kcontrol/kfontinst/kcmfontinst/cr32-action-newfont.png
Binary files differ
diff --git a/kcontrol/kfontinst/kcmfontinst/kcmfontinst.desktop b/kcontrol/kfontinst/kcmfontinst/kcmfontinst.desktop
new file mode 100644
index 000000000..e8460ab49
--- /dev/null
+++ b/kcontrol/kfontinst/kcmfontinst/kcmfontinst.desktop
@@ -0,0 +1,235 @@
+[Desktop Entry]
+Exec=kcmshell kcmfontinst
+Icon=fonts
+Type=Application
+DocPath=kcontrol/kcmfontinst/index.html
+
+
+X-KDE-Library=fontinst
+X-KDE-FactoryName=fontinst
+X-KDE-RootOnly=true
+
+X-KDE-ParentApp=kcontrol
+
+Name=Font Installer
+Name[af]=Skrif tipe Installeerder
+Name[ar]=مثبت المحارف
+Name[az]=Yazı Növü Qurucusu
+Name[be]=Устаноўка шрыфтоў
+Name[bg]=Шрифтове
+Name[bn]=ফন্ট ইনস্টলার
+Name[br]=Stalianer an nodrezhoù
+Name[bs]=Dodavanje fontova
+Name[ca]=Instal·lador de lletres
+Name[cs]=Instalátor písem
+Name[csb]=Instalownik fòntów
+Name[cy]=Gosodydd Ffontiau
+Name[da]=Skrifttype-installering
+Name[de]=Schriftarteninstallation
+Name[el]=Εγκαταστάτης γραμματοσειρών
+Name[eo]=Tiparinstalilo
+Name[es]=Instalador de tipos de letra
+Name[et]=Fontide paigaldaja
+Name[eu]=Letra tipoak instalatzeko tresna
+Name[fa]=نصب‌کنندۀ قلم
+Name[fi]=Kirjasinasentaja
+Name[fr]=Installateur de polices
+Name[fy]=Lettertype-Ynstalaasje
+Name[ga]=Suiteálaí Clófhoirne
+Name[gl]=Instalador de Fontes
+Name[he]=מתקין הגופנים
+Name[hi]=फ़ॉन्ट संस्थापक
+Name[hr]=Instaliranje fontova
+Name[hu]=Betűtípus-telepítő
+Name[is]=KDE letursækir
+Name[it]=Installatore dei tipi di carattere
+Name[ja]=フォントインストーラ
+Name[ka]=ფონტების დაყენება
+Name[kk]=Қаріптерді орнату
+Name[km]=កម្មវិធី​ដំឡើង​ពុម្ពអក្សរ
+Name[ko]=글꼴 설치기
+Name[lo]=ຕິດຕັ້ງຮູບແບບຕົວອັກສອນ
+Name[lt]=Šriftų diegiklis
+Name[lv]=Fontu Instalators
+Name[mk]=Инсталатор на фонтови
+Name[mn]=Бичиг-Суулгалт
+Name[ms]=Pemasang Fon
+Name[mt]=Installatur ta' fonts
+Name[nb]=Skriftinstallering
+Name[nds]=Schriftoorden installeren
+Name[ne]=फन्ट स्थापक
+Name[nl]=Lettertype-installatie
+Name[nn]=Skriftinstallering
+Name[nso]=Motsenyi wa Fonto
+Name[pa]=ਫੋਂਟ ਇੰਸਟਾਲਰ
+Name[pl]=Instalator czcionek
+Name[pt]=Instalador de Tipos de Letra
+Name[pt_BR]=Instalador de Fontes
+Name[ro]=Instalare fonturi
+Name[ru]=Установка шрифтов
+Name[rw]=Mwinjizaporogaramu Imyandikire
+Name[se]=Fontasajáiduhttejeaddji
+Name[sk]=Inštalátor písiem
+Name[sl]=Namestilnik pisav
+Name[sr]=Инсталатор фонтова
+Name[sr@Latn]=Instalator fontova
+Name[sv]=Installation av teckensnitt
+Name[ta]=எழுத்துரு நிறுவுதல்
+Name[tg]=Барпо кардани ҳарфҳо
+Name[th]=ตัวติดตั้งแบบอักษร
+Name[tr]=Yazıtipi Kurucusu
+Name[tt]=Yazu Quydırğıç
+Name[uk]=Встановлення шрифтів
+Name[uz]=Shrift oʻrnatgich
+Name[uz@cyrillic]=Шрифт ўрнатгич
+Name[ven]=Mudzhenisi wa Fontu
+Name[vi]=Cài đặt Phông chữ
+Name[wa]=Astaleu di fontes
+Name[xh]=Umfaki Wohlobo lwegama
+Name[zh_CN]=字体安装程序
+Name[zh_TW]=字型安裝程式
+Name[zu]=Umfakeli Wohlobo lwamagama
+
+Comment=Install & preview fonts
+Comment[af]=Installeer & voorskou skriftipes
+Comment[ar]=تثبيت و معاينة المحارف
+Comment[az]=Yazı növü qur & nümayiş et
+Comment[be]=Устаноўка і прагляд шрыфтоў
+Comment[bg]=Инсталиране и преглед на шрифтове
+Comment[bn]=ফন্ট ইনস্টল এবং প্রাক্‌দর্শন করুন
+Comment[br]=Staliañ ha rakgwel an nodrezhoù
+Comment[bs]=Dodavanje i pregledanje fontova
+Comment[ca]=Instal·la i previsualitza lletres
+Comment[cs]=Instalace a náhled písem
+Comment[csb]=Instalacëjô ë pòdzérk fòntów
+Comment[cy]=Gosod a rhagolygu ffontiau
+Comment[da]=Installér og forhåndsvis skrifttyper
+Comment[de]=Schriftarten installieren und betrachten
+Comment[el]=Εγκατάσταση & προεπισκόπηση γραμματοσειρών
+Comment[eo]=Instalas kaj prezentas tiparojn
+Comment[es]=Instalar y previsualizar tipos de letra
+Comment[et]=Fontide paigaldamine ja eelvaatlus
+Comment[eu]=Instalatu eta aurreikusi letra tipoak
+Comment[fa]=نصب و پیش‌نمایش قلمها
+Comment[fi]=Asenna ja esikatsele kirjasimia
+Comment[fr]=Pour installer et afficher des polices de caractères
+Comment[fy]=Lettertypen ynstallearje en besjen
+Comment[ga]=Suiteáil & Réamhamharc na gClónna
+Comment[gl]=Instalar e antever fontes
+Comment[he]=התקנה ותצוגה מקדימה של גופנים
+Comment[hi]=फ़ॉन्ट्स संस्थापित व पूर्वावलोकन करें
+Comment[hr]=Instaliranje i pregled fontova
+Comment[hu]=Betűtípusok telepítése, áttekintése
+Comment[is]=Setja inn & forskoða letur
+Comment[it]=Installa e mostra anteprime dei caratteri
+Comment[ja]=フォントのインストールとプレビュー
+Comment[ka]=ფონტების დაყენება და დათვალიერება
+Comment[kk]=Қаріптерді орнату және қарап-шығу
+Comment[km]=ដំឡើង & មើល​ពុម្ពអក្សរ​ជា​មុន
+Comment[ko]=글꼴 설치, 미리보기, 관리
+Comment[lo]=ຕິດຕັ້ງແລະສະແດງຕົວຢ່າງຮູບແບບຕົວອັກສອນ
+Comment[lt]=Instaliuoja ir peržiūri šriftus
+Comment[lv]=Instalē un apskata fontus
+Comment[mk]=Инсталирај и прегледај фонтови
+Comment[mn]=Бичиг суулгах ба харах
+Comment[ms]=Pasang & prapapar fon
+Comment[mt]=Installa u ara fonts
+Comment[nb]=Installer og forhåndsvis skrifttyper
+Comment[nds]=Schriftoorden installeren & ankieken
+Comment[ne]=फन्ट स्थापना र पूर्वावलोकन गर्नुहोस्
+Comment[nl]=Lettertypen installeren en bekijken
+Comment[nn]=Installer og vis skrifter
+Comment[nso]=Tsenya & Bonelapele difonto
+Comment[pa]=ਫੋਂਟ ਝਲਕ ਤੇ ਇੰਸਟਾਲ
+Comment[pl]=Instalacja i podgląd czcionek
+Comment[pt]=Instalar e antever tipos de letra
+Comment[pt_BR]=Instalar & pré-visualizar fontes
+Comment[ro]=Instalează și previzualizează fonturi
+Comment[ru]=Установка и просмотр шрифтов
+Comment[rw]=Kwinjiza & kugaragazambere imyandikire
+Comment[se]=Sajáiduhtte ja čájet fonttaid
+Comment[sk]=Inštaluje a zobrazuje písma
+Comment[sl]=Namesti in prikaže pisave
+Comment[sr]=Инсталација и преглед фонтова
+Comment[sr@Latn]=Instalacija i pregled fontova
+Comment[sv]=Installera och förhandsgranska teckensnitt
+Comment[ta]=எழுத்துருக்களை நிறுவி காட்டு
+Comment[tg]=Барпо кардан ва тамошои ҳарфҳо
+Comment[th]=ติดตั้งและแสดงตัวอย่างแบบอักษร
+Comment[tr]=Yazıtiplerini kur ve önizle
+Comment[tt]=Yazu şäkellären quyu/tikşerü urını
+Comment[uk]=Встановлення та перегляд шрифтів
+Comment[uz]=Shriftlarni oʻrnatish va koʻrib chiqish
+Comment[uz@cyrillic]=Шрифтларни ўрнатиш ва кўриб чиқиш
+Comment[ven]=Dzhenisani & vhonelani phanda dzifontu
+Comment[vi]=Cài đặt & xem trước phông chữ
+Comment[wa]=Astalaedje et håynaedje des fontes
+Comment[xh]=Faka & yenza imboniso yohlobo lwamagama
+Comment[zh_CN]=安装和预览字体
+Comment[zh_TW]=安裝並預覽字型
+Comment[zu]=Fakela & buka ngaphambili izinhlobo zamagama
+
+Keywords=font,fonts,installer,truetype,type1,speedo,bitmap
+Keywords[be]=Шрыфт,Шрыфты,Устаноўка,font,fonts,installer,truetype,type1,speedo,bitmap
+Keywords[bg]=шрифт, шрифтове, преглед, печат, font, fonts, installer, truetype, type1, speedo, bitmap
+Keywords[br]=nodrezh,nodrezhoù,stalier,truetype,type1,speedo,bitmap
+Keywords[bs]=font,fonts,installer,truetype,type1,speedo,bitmap,fontovi,instalacija
+Keywords[ca]=lletra,lletres,instal·lador,truetype,type1,speedo,bitmap
+Keywords[cs]=písmo,písma,instalátor,truetype,type1,speedo,bitmap
+Keywords[csb]=fòntë,font,instalownik,truetype,type1,speedo
+Keywords[cy]=ffont,ffontiau,wynebfath, wynebfathau,arsefydlydd,truetype,type1,math 1,speedo,didfap
+Keywords[da]=skrifttype,skrifttyper,installatør,truetype,type1,speedo,bitmap
+Keywords[de]=Fonts,Schriftarten,Installation,TrueType,Type1,Speedo,Bitmapschriften
+Keywords[el]=γραμματοσειρά,γραμματοσειρές,εγκαταστάτης,truetype,type1,speedo,bitmap
+Keywords[eo]=tiparo,tiparoj,instalilo,ŝangebla,neŝangebla
+Keywords[es]=tipo de letra,tipos de letra,instalador,truetype,type1,speedo,bitmap
+Keywords[et]=font,fondid,paigaldaja,truetype,type1,speedo,bitmap
+Keywords[eu]=letra-tipoa,letra-tipoak,instalatzailea,truetype,type1,speedo,bitmap
+Keywords[fa]=قلم، قلمها، نصب‌کننده، قلم حقیقی، نوع۱ ،speedo، نگاشت بیت،
+Keywords[fi]=kirjasin,kirjasimet,fontti,fontit,asentaja,truetype,type1,speedo,bitmap
+Keywords[fr]=police,polices,installeur,installateur,truetype,type1,speedo,bitmap
+Keywords[fy]=letters,lettertypen,fonts,Ynstalaasje,truetype,type1,speedo,bitmap
+Keywords[ga]=cló,clónna,clófhoirne,suiteálaí,truetype,type1,speedo,mapa giotán,giotánmhapach
+Keywords[gl]=fonte,fontes,instalador,truetype,type1,speedo,bitmap
+Keywords[he]=גופנים,גופן, מתקין, TrueType, Type1, speedo, מפת סיביות, bitmap, font,fonts,installer,truetype,type1,speedo,bitmap
+Keywords[hi]=फ़ॉन्ट,फ़ॉन्ट्स,संस्थापक,ट्रू-टाइप,टाइप-1,स्पीडो,बिटमैप
+Keywords[hr]=font,fonts,installer,truetype,type1,speedo,bitmap,fontovi,instaliranje,TTF
+Keywords[hu]=betűtípus,betűtípusok,telepítő,TrueType,Type1,Speedo,bittérkép
+Keywords[is]=font,fonts,installer,truetype,type1,speedo,bitmap,letur
+Keywords[it]=font,caratteri,installatore,truetype,type1,speedo,bitmap,tipi di carattere
+Keywords[ja]=フォント,インストーラ,truetype,type1,speedo,bitmap,ビットマップ
+Keywords[ka]=ფონტი,ფონტები,დასაყენებელი,truetype,type1,speedo,bitmap
+Keywords[km]=ពុម្ពអក្សរ,កម្មវិធី​ដំឡើង,truetype,type1,speedo,bitmap
+Keywords[lt]=šriftas,šriftai,įdiegimas,truetype,type1,speedo,bitmap
+Keywords[lv]=fonti,fonts,instalēt,truetype,type1,speedo,bitmap
+Keywords[mk]=font,fonts,installer,truetype,type1,speedo,bitmap,фонт,фонтови,инсталатор
+Keywords[nb]=skrift,skrifter,skrifttype,skrifttyper,installer,truetype,type1,speedo,bitmap
+Keywords[nds]=Schriftoort,Schriftoorden,Installeren,TrueType,Type1,Speedo,Bitmap
+Keywords[ne]=फन्ट, फन्टहरू, स्थापक, ट्रु टाइप, टाइप १, स्पेडो, बिटम्याप
+Keywords[nl]=letters,lettertypen,fonts,installatie,truetype,type1,speedo,bitmap
+Keywords[nn]=skrift,skrifter,installering,truetype,type1,speedo,bitmap
+Keywords[pa]=font,fonts,installer,truetype,type1,speedo,bitmap, ਫੋਂਟ, ਇੰਸਟਾਲਰ
+Keywords[pl]=czcionka,czcionki,font,instalator,truetype,type1,speedo
+Keywords[pt]=tipo de letra,tipos de letra,instalador,truetype,type1,speedo,imagem
+Keywords[pt_BR]=fonte,fontes,instalador,truetype,type1,speedo,bitmap
+Keywords[ro]=font,fonturi,instalator,truetype,type1,speedo,bitmap
+Keywords[ru]=font,fonts,installer,truetype,type1,speedo,bitmap,шрифты
+Keywords[rw]=Imyandikire,imyandikire,mwinjiza,ubwokonyabwo,ubwoko1,umuvuduko,bitimapu
+Keywords[se]=fonta,fonttat,sajáiduhttejeaddji,truetype,type1,speedo,bitmap
+Keywords[sk]=písmo,písma,inštalátor,truetype,type1,speedo,bitmap
+Keywords[sl]=pisava,pisave,namestilnik,truetype,type1,speedo,bitmap
+Keywords[sr]=font,fonts,installer,truetype,type1,speedo,bitmap,фонт,фонтови,инсталер,битмапа
+Keywords[sr@Latn]=font,fonts,installer,truetype,type1,speedo,bitmap,font,fontovi,instaler,bitmapa
+Keywords[sv]=teckensnitt,installation,truetype,type1,speedo,bitmap
+Keywords[ta]=எழுத்துரு,எழுத்துருக்கள்,அமர்வர்,மெய்வகை,வகை1,speedo,பிட்படம்
+Keywords[th]=แบบอักษร,ตัวติดตั้ง,ทรูไทป์,ไทป์1,speedo,บิตแมป
+Keywords[tr]=yazıtipi,yazıtipleri,kurucu,truetype,type1,speedo,bitmap
+Keywords[uk]=шрифт, шрифти,встановлення,векторний,растровий,truetype,type1,speedo
+Keywords[uz]=shrift,shriftlar,oʻrnatuvchi,bitmap,truetype,type1,speedo
+Keywords[uz@cyrillic]=шрифт,шрифтлар,ўрнатувчи,битмап,truetype,type1,speedo
+Keywords[vi]=phông chữ,các phông chữ,trình cài đặt,truetype,kiểu 1,tốc độ gõ,mảng ảnh
+Keywords[wa]=fonte,fontes,astaleu,truetype,type1,speedo,bitmap
+Keywords[zh_CN]=font,fonts,installer,truetype,type1,speedo,bitmap,字体,安装程序,位图字体
+Keywords[zh_TW]=font,fonts,installer,truetype,type1,speedo,bitmap,字型,安裝程式,點陣
+
+Categories=Qt;KDE;X-KDE-settings-system;
diff --git a/kcontrol/kfontinst/kfile-plugin/KFileFont.cpp b/kcontrol/kfontinst/kfile-plugin/KFileFont.cpp
new file mode 100644
index 000000000..31fbaa83e
--- /dev/null
+++ b/kcontrol/kfontinst/kfile-plugin/KFileFont.cpp
@@ -0,0 +1,422 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : KFI::KFileFont
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 20/03/2003
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2003, 2004
+////////////////////////////////////////////////////////////////////////////////
+
+#include "KFileFont.h"
+#include "KfiConstants.h"
+#include <qfile.h>
+#include <qtextstream.h>
+#include <kgenericfactory.h>
+#include <kio/netaccess.h>
+
+static void addEntry(int face, QString &existing, const QString &add)
+{
+ if(face>0)
+ existing.append(", ");
+ existing.append(add);
+}
+
+static int strToWeight(const QString &str)
+{
+ if(NULL==str)
+ return FC_WEIGHT_MEDIUM;
+ else if(str.contains("Bold", false))
+ return FC_WEIGHT_BOLD;
+ else if(str.contains("Heavy", false))
+ return FC_WEIGHT_HEAVY;
+ else if(str.contains("Black", false))
+ return FC_WEIGHT_BLACK;
+ else if(str.contains("ExtraBold", false))
+ return FC_WEIGHT_EXTRABOLD;
+ else if(str.contains("UltraBold", false))
+ return FC_WEIGHT_ULTRABOLD;
+ else if(str.contains("ExtraLight", false))
+ return FC_WEIGHT_EXTRALIGHT;
+ else if(str.contains("UltraLight", false))
+ return FC_WEIGHT_ULTRALIGHT;
+ else if(str.contains("Light", false))
+ return FC_WEIGHT_LIGHT;
+ else if(str.contains("Medium", false) || str.contains("Normal", false) || str.contains("Roman", false))
+ return FC_WEIGHT_MEDIUM;
+ else if(str.contains("Regular", false))
+ return FC_WEIGHT_REGULAR;
+ else if(str.contains("SemiBold", false))
+ return FC_WEIGHT_SEMIBOLD;
+ else if(str.contains("DemiBold", false))
+ return FC_WEIGHT_DEMIBOLD;
+ else if(str.contains("Thin", false))
+ return FC_WEIGHT_THIN;
+ else if(str.contains("Book", false))
+ return FC_WEIGHT_NORMAL;
+ else if(str.contains("Demi", false))
+ return FC_WEIGHT_NORMAL;
+ else
+ return FC_WEIGHT_MEDIUM;
+}
+
+#ifndef KFI_FC_NO_WIDTHS
+static int strToWidth(const QString &str)
+{
+ if(str.isEmpty())
+ return FC_WIDTH_NORMAL;
+ else if(str.contains("UltraCondensed", false))
+ return FC_WIDTH_ULTRACONDENSED;
+ else if(str.contains("ExtraCondensed", false))
+ return FC_WIDTH_EXTRACONDENSED;
+ else if(str.contains("SemiCondensed", false))
+ return FC_WIDTH_SEMICONDENSED;
+ else if(str.contains("Condensed", false))
+ return FC_WIDTH_CONDENSED;
+ else if(str.contains("SemiExpanded", false))
+ return FC_WIDTH_SEMIEXPANDED;
+ else if(str.contains("UltraExpanded", false))
+ return FC_WIDTH_ULTRAEXPANDED;
+ else if(str.contains("ExtraExpanded", false))
+ return FC_WIDTH_EXTRAEXPANDED;
+ else if(str.contains("Expanded", false))
+ return FC_WIDTH_EXPANDED;
+ else
+ return FC_WIDTH_NORMAL;
+}
+#endif
+
+struct FoundryMap
+{
+ const char *noticeStr,
+ *foundry;
+ unsigned short len;
+};
+
+static const FoundryMap map[]= // These are (mainly) taken from type1inst
+{
+ { "Bigelow", "B&H", 3},
+ { "Adobe", "Adobe", 5},
+ { "Bitstream", "Bitstream", 9},
+ { "Monotype", "Monotype", 8},
+ { "Linotype", "Linotype", 8},
+ { "LINOTYPE-HELL", "Linotype", 0},
+ { "IBM", "IBM", 3},
+ { "URW", "URW", 3},
+ { "International Typeface Corporation", "ITC", 3},
+ { "Tiro Typeworks", "Tiro", 4},
+ { "XFree86", "XFree86", 7},
+ { "Microsoft", "Microsoft", 9},
+ { "Omega", "Omega", 5},
+ { "Font21", "Hwan", 4},
+ { "HanYang System", "Hanyang", 7},
+ { "Richard Mitchell", "Mitchell", 8},
+ { "Doug Miles", "Miles", 5},
+ { "Hank Gillette", "Gillette", 8},
+ { "Three Islands Press", "3ip", 3},
+ { "MacroMind", "Macromind", 9},
+ { "MWSoft", "MWSoft", 6},
+ { "Digiteyes Multimedia", "DigitEyes", 9},
+ { "ZSoft", "ZSoft", 5},
+ { "Title Wave", "Titlewave", 9},
+ { "Southern Software", "Southern", 8},
+ { "Reasonable Solutions", "Reasonable", 10},
+ { "David Rakowski", "Rakowski", 8},
+ { "D. Rakowski", "Rakowski", 0},
+ { "S. G. Moye", "Moye", 4},
+ { "S.G. Moye", "Moye", 0},
+ { "Andrew s. Meit", "Meit", 4},
+ { "A.S.Meit", "Meit", 0},
+ { "Hershey", "Hershey", 7},
+ { "FontBank", "FontBank", 8},
+ { "A. Carr", "Carr", 4},
+ { "Brendel Informatik", "Brendel", 7},
+ { "Jonathan Brecher", "Brecher", 7},
+ { "SoftMaker", "Softmaker", 9},
+ { "LETRASET", "Letraset", 8},
+ { "Corel Corp", "Corel", 5},
+ { "PUBLISHERS PARADISE", "Paradise", 8},
+ { "Publishers Paradise", "Paradise", 0},
+ { "Allied Corporation", "Allied", 6},
+ { NULL, NULL, 0}
+};
+
+static const char * getFoundry(const char *notice)
+{
+ const FoundryMap *entry;
+
+ if(notice)
+ for(entry=map; NULL!=entry->foundry; entry++)
+ if(NULL!=strstr(notice, entry->noticeStr))
+ return entry->foundry;
+
+ return NULL;
+}
+
+static bool readAfm(const QString &file, QString &full, QString &family, QString &foundry, QString &weight,
+#ifndef KFI_FC_NO_WIDTHS
+ QString &width,
+#endif
+ QString &spacing, QString &slant)
+{
+ QFile f(file);
+ bool foundName=false,
+ foundFamily=false;
+ int intSpacing=FC_PROPORTIONAL,
+#ifndef KFI_FC_NO_WIDTHS
+ intWidth=FC_WIDTH_NORMAL,
+#endif
+ intWeight=FC_WEIGHT_NORMAL,
+ intSlant=FC_SLANT_ROMAN,
+ intItalic=FC_SLANT_ROMAN;
+
+ if(f.open(IO_ReadOnly))
+ {
+ QTextStream stream(&f);
+ QString line;
+ bool inMetrics=false;
+
+ while(!stream.atEnd())
+ {
+ line=stream.readLine();
+ line=line.simplifyWhiteSpace();
+
+ if(inMetrics)
+ {
+ if(0==line.find("FullName "))
+ {
+ full=line.mid(9);
+#ifndef KFI_FC_NO_WIDTHS
+ intWidth=strToWidth(full);
+#endif
+ foundName=true;
+ }
+ else if(0==line.find("FamilyName "))
+ {
+ family=line.mid(11);
+ foundFamily=true;
+ }
+ else if(0==line.find("Weight "))
+ intWeight=strToWeight(line.mid(7));
+ else if(0==line.find("ItalicAngle "))
+ intSlant=0.0f==line.mid(12).toFloat() ? FC_SLANT_ROMAN : FC_SLANT_ITALIC;
+ else if(0==line.find("IsFixedPitch "))
+ intSpacing=0==line.mid(13).find("false", 0, false) ? FC_PROPORTIONAL : FC_MONO;
+ else if(0==line.find("Notice "))
+ foundry=getFoundry(line.mid(7).latin1());
+ else if(0==line.find("StartCharMetrics"))
+ break;
+ }
+ else
+ if(0==line.find("StartFontMetrics"))
+ inMetrics=true;
+ };
+ f.close();
+
+ if(!foundFamily && foundName)
+ {
+ family=full;
+ foundFamily=true;
+ }
+
+ if(foundName && FC_SLANT_ITALIC==intItalic && (-1!=full.find("Oblique") || -1!=full.find("Slanted")))
+ intItalic=FC_SLANT_OBLIQUE;
+ }
+
+ if(foundName && foundFamily)
+ {
+ weight=KFI::CFcEngine::weightStr(intWeight, false);
+#ifndef KFI_FC_NO_WIDTHS
+ width=KFI::CFcEngine::widthStr(intWidth, false);
+#endif
+ slant=KFI::CFcEngine::slantStr(intSlant, false);
+ spacing=KFI::CFcEngine::spacingStr(intSpacing);
+
+ if(foundry.isEmpty())
+ foundry=i18n(KFI_UNKNOWN_FOUNDRY);
+
+ return true;
+ }
+
+ return false;
+}
+
+typedef KGenericFactory<KFI::KFileFontPlugin> KFileFontPluginFactory;
+K_EXPORT_COMPONENT_FACTORY(kfile_font, KFileFontPluginFactory("kfontinst"))
+
+namespace KFI
+{
+
+KFileFontPlugin::KFileFontPlugin(QObject *parent, const char *name, const QStringList& args)
+ : KFilePlugin(parent, name, args)
+{
+ KGlobal::locale()->insertCatalogue(KFI_CATALOGUE);
+
+ addMimeType("application/x-font-ttf"),
+ addMimeType("application/x-font-type1");
+ //addMimeType("application/x-font-speedo");
+ addMimeType("application/x-font-bdf");
+ addMimeType("application/x-font-pcf");
+ //addMimeType("application/x-font-snf");
+ addMimeType("application/x-font-otf");
+ addMimeType("application/x-font-ttc");
+ addMimeType("application/x-afm");
+}
+
+void KFileFontPlugin::addMimeType(const char *mime)
+{
+ KFileMimeTypeInfo *info=addMimeTypeInfo(mime);
+ KFileMimeTypeInfo::GroupInfo *group=addGroupInfo(info, "General", i18n("General"));
+
+ addItemInfo(group, "Full", i18n("Full Name"), QVariant::String);
+ addItemInfo(group, "Family", i18n("Family"), QVariant::String);
+ addItemInfo(group, "Foundry", i18n("Foundry"), QVariant::String);
+ addItemInfo(group, "Weight", i18n("Weight"), QVariant::String);
+#ifndef KFI_FC_NO_WIDTHS
+ addItemInfo(group, "Width", i18n("Width"), QVariant::String);
+#endif
+ addItemInfo(group, "Spacing", i18n("Spacing"), QVariant::String);
+ addItemInfo(group, "Slant", i18n("Slant"), QVariant::String);
+}
+
+bool KFileFontPlugin::readInfo(KFileMetaInfo& info, uint what)
+{
+ QString full,
+ lastFull,
+ family,
+ foundry,
+ weight,
+#ifndef KFI_FC_NO_WIDTHS
+ width,
+#endif
+ spacing,
+ slant,
+ fullAll,
+ familyAll,
+ foundryAll,
+ weightAll,
+#ifndef KFI_FC_NO_WIDTHS
+ widthAll,
+#endif
+ spacingAll,
+ slantAll;
+ KURL url(info.url());
+ QString fName;
+ bool fontsProt = KFI_KIO_FONTS_PROTOCOL == url.protocol(),
+ fileProt = "file" == url.protocol(),
+ downloaded = false,
+ status = false;
+
+ what=0;
+
+ if(!fontsProt && !fileProt && KIO::NetAccess::download(url, fName, NULL))
+ {
+ downloaded=true;
+ url=KURL(fName);
+ }
+
+ if(downloaded || fontsProt || fileProt)
+ {
+ if("application/x-afm"==info.mimeType()) // Then fontconfig can't give us the data :-(
+ status=readAfm(url.path(), fullAll, familyAll, foundryAll, weightAll,
+#ifndef KFI_FC_NO_WIDTHS
+ widthAll,
+#endif
+ spacingAll, slantAll);
+ else
+ for(int face=0; face<10; ++face) // How to get num faces from fontconfig? don't know - so just try 1st 10...
+ {
+ if(itsEngine.getInfo(url, face, full, family, foundry, weight,
+#ifndef KFI_FC_NO_WIDTHS
+ width,
+#endif
+ spacing, slant) &&
+ !full.isEmpty() && full!=lastFull)
+ {
+ addEntry(face, fullAll, full);
+ lastFull=full;
+
+ if(KFileMetaInfo::Fastest!=what)
+ {
+ addEntry(face, familyAll, family);
+ if(0==face)
+ {
+ foundryAll=foundry;
+
+ if(foundryAll.isEmpty())
+ foundryAll=i18n(KFI_UNKNOWN_FOUNDRY);
+ else
+ {
+ // Try to make sure foundry is capitalised, and looks the same as that of
+ // any AFM.
+ foundryAll[0]=foundryAll[0].upper();
+
+ const FoundryMap *entry;
+
+ for(entry=map; NULL!=entry->foundry; entry++)
+ if(foundryAll.length()==entry->len && foundryAll.contains(entry->foundry, false))
+ {
+ foundryAll=entry->foundry;
+ break;
+ }
+ }
+ }
+ addEntry(face, weightAll, weight);
+#ifndef KFI_FC_NO_WIDTHS
+ addEntry(face, widthAll, width);
+#endif
+ addEntry(face, spacingAll, spacing);
+ addEntry(face, slantAll, slant);
+ }
+ status=true;
+ }
+ else
+ break;
+ }
+
+ if(status)
+ {
+ KFileMetaInfoGroup group;
+
+ group=appendGroup(info, "General");
+ appendItem(group, "Full", fullAll);
+
+ if(KFileMetaInfo::Fastest!=what)
+ {
+ appendItem(group, "Family", familyAll);
+ appendItem(group, "Foundry", foundryAll);
+ appendItem(group, "Weight", weightAll);
+#ifndef KFI_FC_NO_WIDTHS
+ appendItem(group, "Width", widthAll);
+#endif
+ appendItem(group, "Spacing", spacingAll);
+ appendItem(group, "Slant", slantAll);
+ }
+ }
+
+ if(downloaded)
+ KIO::NetAccess::removeTempFile(fName);
+ }
+
+ return status;
+}
+
+}
diff --git a/kcontrol/kfontinst/kfile-plugin/KFileFont.h b/kcontrol/kfontinst/kfile-plugin/KFileFont.h
new file mode 100644
index 000000000..b06ab2a57
--- /dev/null
+++ b/kcontrol/kfontinst/kfile-plugin/KFileFont.h
@@ -0,0 +1,58 @@
+#ifndef __KFILE_FONT_H__
+#define __KFILE_FONT_H__
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : KFileFont
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 20/03/2003
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2003, 2004
+////////////////////////////////////////////////////////////////////////////////
+
+#include <kfilemetainfo.h>
+#include "FcEngine.h"
+
+namespace KFI
+{
+
+class KFileFontPlugin : public KFilePlugin
+{
+ public:
+
+ KFileFontPlugin(QObject *parent, const char *name, const QStringList& args);
+ virtual ~KFileFontPlugin() {}
+
+ bool readInfo(KFileMetaInfo& info, uint what = KFileMetaInfo::Fastest);
+
+ private:
+
+ void addMimeType(const char *mime);
+
+ private:
+
+ CFcEngine itsEngine;
+};
+
+}
+
+#endif
diff --git a/kcontrol/kfontinst/kfile-plugin/Makefile.am b/kcontrol/kfontinst/kfile-plugin/Makefile.am
new file mode 100644
index 000000000..7f136357f
--- /dev/null
+++ b/kcontrol/kfontinst/kfile-plugin/Makefile.am
@@ -0,0 +1,13 @@
+kde_module_LTLIBRARIES = kfile_font.la
+
+kfile_font_la_SOURCES = KFileFont.cpp
+kfile_font_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIBFREETYPE_RPATH) -module $(KDE_PLUGIN)
+kfile_font_la_LIBADD = $(LIB_KIO) $(LIBFREETYPE_LIBS) ../lib/libkfontinst.la
+
+kdelnkdir = $(kde_servicesdir)
+kde_services_DATA = kfile_font.desktop
+
+AM_CPPFLAGS = -I$(srcdir)/../lib -I$(srcdir)/../../fonts $(all_includes) $(LIBFREETYPE_CFLAGS)
+
+METASOURCES = AUTO
+noinst_HEADERS = KFileFont.h
diff --git a/kcontrol/kfontinst/kfile-plugin/kfile_font.desktop b/kcontrol/kfontinst/kfile-plugin/kfile_font.desktop
new file mode 100644
index 000000000..7ac0a499f
--- /dev/null
+++ b/kcontrol/kfontinst/kfile-plugin/kfile_font.desktop
@@ -0,0 +1,86 @@
+[Desktop Entry]
+Type=Service
+Name=Font Information
+Name[af]=Skrif tipe Informasie
+Name[ar]=معلومات المحرف
+Name[az]=Yazı Növü Mə'lumatı
+Name[be]=Інфармацыя аб шрыфце
+Name[bg]=Информация за шрифт
+Name[bn]=ফন্ট তথ্য
+Name[br]=Titouroù diwar-benn ar font
+Name[bs]=Informacije o fontu
+Name[ca]=Informació de la lletra
+Name[cs]=Informace o písmu
+Name[csb]=Wëdowiédzô ò fòntach
+Name[cy]=Gwybodaeth Ffont
+Name[da]=Skrifttypeinformation
+Name[de]=Schriftarteninformation
+Name[el]=Πληροφορίες γραμματοσειράς
+Name[eo]=Tiparinformo
+Name[es]=Información del tipo de letra
+Name[et]=Fondi info
+Name[eu]=Letra-tipoei buruzko informazioa
+Name[fa]=اطلاعات قلم
+Name[fi]=Kirjasintiedot
+Name[fr]=Informations sur les polices
+Name[fy]=Lettertype-Ynformaasje
+Name[ga]=Eolas Clófhoirne
+Name[gl]=Información da Fonte
+Name[he]=מידע גופנים
+Name[hi]=फ़ॉन्ट जानकारी
+Name[hr]=Podaci o fontu
+Name[hu]=Betűtípus-jellemzők
+Name[id]=Informasi Font
+Name[is]=Leturupplýsingar
+Name[it]=Informazioni caratteri
+Name[ja]=フォント情報
+Name[ka]=ინფორმაცია ფონტის შესახებ
+Name[kk]=Қаріп мәліметі
+Name[km]=ព័ត៌មាន​ពុម្ពអក្សរ
+Name[ko]=연락처 정보
+Name[lo]=ຂໍ້ມູນຕ່າງໆ
+Name[lt]=Šrifto(-ų) informacija
+Name[lv]=Fontu Informācija
+Name[mk]=Информации за фонтовите
+Name[mn]=Бичиг-Мэдээлэл
+Name[ms]=Maklumat Fon
+Name[mt]=Informazzjoni dwar font
+Name[nb]=Skriftinformasjon
+Name[nds]=Schriftoort-Informatschoon
+Name[ne]=फन्ट सूचना
+Name[nl]=Lettertype-informatie
+Name[nn]=Skriftinformasjon
+Name[nso]=Tshedimoso ya Fonto
+Name[pa]=ਫੋਂਟ ਜਾਣਕਾਰੀ
+Name[pl]=Informacje o czcionkach
+Name[pt]=Informação do Tipo de Letra
+Name[pt_BR]=Informações sobre a Fonte
+Name[ro]=Informații font
+Name[ru]=Сведения о шрифте
+Name[rw]=Amakuru y'Imyandikire
+Name[se]=Fontadieđut
+Name[sk]=Informácie o písmach
+Name[sl]=Informacije o pisavi
+Name[sr]=Информације о фонту
+Name[sr@Latn]=Informacije o fontu
+Name[sv]=Teckensnittsinformation
+Name[ta]=எழுத்துரு தகவல்
+Name[tg]=Иттилооти ҳарфҳо
+Name[th]=ข้อมูลแบบอักษร
+Name[tr]=Yazıtipi Bilgisi
+Name[tt]=Yazu Turında
+Name[uk]=Інформація про шрифти
+Name[uz]=Shrift haqida maʼlumot
+Name[uz@cyrillic]=Шрифт ҳақида маълумот
+Name[ven]=Mafhungo a fontu
+Name[vi]=Thông tin về Phông chữ
+Name[wa]=Informåcion sol fonte
+Name[xh]=Ulwazi Lohlobo lwamagama
+Name[zh_CN]=字体信息
+Name[zh_TW]=字型資訊
+Name[zu]=Ulwazi lohlobo lwamagama
+ServiceTypes=KFilePlugin
+X-KDE-Library=kfile_font
+MimeType=application/x-font-ttf;application/x-font-type1;application/x-font-bdf;application/x-font-pcf;application/x-font-otf;application/x-font-ttc;application/x-afm
+PreferredGroups=General
+PreferredItems=Full,Family,Foundry,Weight,Width,Spacing,Slant
diff --git a/kcontrol/kfontinst/kfontinst/FontEngine.cpp b/kcontrol/kfontinst/kfontinst/FontEngine.cpp
new file mode 100644
index 000000000..ff5dcd623
--- /dev/null
+++ b/kcontrol/kfontinst/kfontinst/FontEngine.cpp
@@ -0,0 +1,376 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : KFI::CFontEngine
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 29/04/2001
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2001, 2002, 2003, 2004
+////////////////////////////////////////////////////////////////////////////////
+
+
+#include "FontEngine.h"
+#include "Misc.h"
+#include <kglobal.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <iostream>
+#include <stdio.h>
+#include <qregexp.h>
+#include <qfile.h>
+#include <ft2build.h>
+#include FT_SFNT_NAMES_H
+#include FT_TRUETYPE_IDS_H
+#include FT_TRUETYPE_TABLES_H
+#include FT_TYPE1_TABLES_H
+
+namespace KFI
+{
+
+bool CFontEngine::openFont(const QString &file, int face)
+{
+ bool ok=false;
+
+ if(file==itsPath && face==itsFaceIndex)
+ {
+ ok=NONE!=itsType;
+ }
+ else
+ {
+ closeFont();
+
+ itsWeight=WEIGHT_MEDIUM;
+ itsItalic=ITALIC_NONE;
+ itsPath=file;
+ itsFaceIndex=face;
+ itsPsName=QString();
+
+ if(!openFontFt(file) && !itsPsName.isEmpty())
+ itsType=NONE;
+ }
+
+ return NONE!=itsType;
+}
+
+void CFontEngine::closeFont()
+{
+ closeFaceFt();
+ itsPath=QString::null;
+ itsFaceIndex=-1;
+ itsType=NONE;
+}
+
+QString CFontEngine::weightStr(enum EWeight w)
+{
+ switch(w)
+ {
+ case WEIGHT_THIN:
+ return "Thin";
+ case WEIGHT_ULTRA_LIGHT:
+ return "UltraLight";
+ case WEIGHT_EXTRA_LIGHT:
+ return "ExtraLight";
+ case WEIGHT_DEMI:
+ return "Demi";
+ case WEIGHT_LIGHT:
+ return "Light";
+ case WEIGHT_BOOK:
+ return "Book";
+ case WEIGHT_MEDIUM:
+ return "Medium";
+ case WEIGHT_REGULAR:
+ return "Regular";
+ case WEIGHT_SEMI_BOLD:
+ return "SemiBold";
+ case WEIGHT_DEMI_BOLD:
+ return "DemiBold";
+ case WEIGHT_BOLD:
+ return "Bold";
+ case WEIGHT_EXTRA_BOLD:
+ return "ExtraBold";
+ case WEIGHT_ULTRA_BOLD:
+ return "UltraBold";
+ case WEIGHT_HEAVY:
+ return "Heavy";
+ case WEIGHT_BLACK:
+ return "Black";
+ case WEIGHT_UNKNOWN:
+ default:
+ return "Medium";
+ }
+}
+
+CFontEngine::EWeight CFontEngine::strToWeight(const char *str)
+{
+ if(NULL==str)
+ return WEIGHT_MEDIUM; // WEIGHT_UNKNOWN;
+ else if(kasciistricmp(str, "Bold")==0)
+ return WEIGHT_BOLD;
+ else if(kasciistricmp(str, "Black")==0)
+ return WEIGHT_BLACK;
+ else if(kasciistricmp(str, "ExtraBold")==0)
+ return WEIGHT_EXTRA_BOLD;
+ else if(kasciistricmp(str, "UltraBold")==0)
+ return WEIGHT_ULTRA_BOLD;
+ else if(kasciistricmp(str, "ExtraLight")==0)
+ return WEIGHT_EXTRA_LIGHT;
+ else if(kasciistricmp(str, "UltraLight")==0)
+ return WEIGHT_ULTRA_LIGHT;
+ else if(kasciistricmp(str, "Light")==0)
+ return WEIGHT_LIGHT;
+ else if(kasciistricmp(str, "Medium")==0 || kasciistricmp(str, "Normal")==0 || kasciistricmp(str, "Roman")==0)
+ return WEIGHT_MEDIUM;
+ else if(kasciistricmp(str, "Regular")==0)
+ return WEIGHT_MEDIUM; // WEIGHT_REGULAR;
+ else if(kasciistricmp(str, "Demi")==0)
+ return WEIGHT_DEMI;
+ else if(kasciistricmp(str, "SemiBold")==0)
+ return WEIGHT_SEMI_BOLD;
+ else if(kasciistricmp(str, "DemiBold")==0)
+ return WEIGHT_DEMI_BOLD;
+ else if(kasciistricmp(str, "Thin")==0)
+ return WEIGHT_THIN;
+ else if(kasciistricmp(str, "Book")==0)
+ return WEIGHT_BOOK;
+ else
+ return WEIGHT_MEDIUM; // WEIGHT_UNKNOWN;
+}
+
+static void removeSymbols(QString &str)
+{
+ str.replace(QRegExp("[\\-\\[\\]()]"), " ");
+
+ int len=str.length();
+ QChar space(' ');
+
+ for(int c=0; c<len; ++c)
+ if(str[c].unicode()<0x20 || str[c].unicode()>0x7E)
+ str[c]=space;
+
+ str=str.simplifyWhiteSpace();
+ str=str.stripWhiteSpace();
+}
+
+static bool lookupName(FT_Face face, int nid, int pid, int eid, FT_SfntName *nameReturn)
+{
+ int n = FT_Get_Sfnt_Name_Count(face);
+
+ if(n>0)
+ {
+ int i;
+ FT_SfntName name;
+
+ for(i=0; i<n; i++)
+ if(0==FT_Get_Sfnt_Name(face, i, &name) && name.name_id == nid && name.platform_id == pid &&
+ (eid < 0 || name.encoding_id == eid))
+ {
+ switch(name.platform_id)
+ {
+ case TT_PLATFORM_APPLE_UNICODE:
+ case TT_PLATFORM_MACINTOSH:
+ if(name.language_id != TT_MAC_LANGID_ENGLISH)
+ continue;
+ break;
+ case TT_PLATFORM_MICROSOFT:
+ if(name.language_id != TT_MS_LANGID_ENGLISH_UNITED_STATES &&
+ name.language_id != TT_MS_LANGID_ENGLISH_UNITED_KINGDOM)
+ continue;
+ break;
+ default:
+ continue;
+ }
+
+ if(name.string_len > 0)
+ {
+ *nameReturn = name;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static QCString getName(FT_Face face, int nid)
+{
+ FT_SfntName name;
+ QCString str;
+
+ if(lookupName(face, nid, TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, &name) ||
+ lookupName(face, nid, TT_PLATFORM_APPLE_UNICODE, -1, &name))
+ for(unsigned int i=0; i < name.string_len / 2; i++)
+ str+=0 == name.string[2*i] ? name.string[(2*i)+1] : '_';
+ else if(lookupName(face, nid, TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, &name)) // Pretend that Apple Roman is ISO 8859-1
+ for(unsigned int i=0; i < name.string_len; i++)
+ str+=name.string[i];
+
+ return str;
+}
+
+bool CFontEngine::openFontFt(const QString &file)
+{
+ enum ETtfWeight
+ {
+ TTF_WEIGHT_UNKNOWN = 0,
+ TTF_WEIGHT_THIN = 100 +50,
+ TTF_WEIGHT_EXTRALIGHT = 200 +50,
+ TTF_WEIGHT_LIGHT = 300 +50,
+ TTF_WEIGHT_NORMAL = 400 +50,
+ TTF_WEIGHT_MEDIUM = 500 +50,
+ TTF_WEIGHT_SEMIBOLD = 600 +50,
+ TTF_WEIGHT_BOLD = 700 +50,
+ TTF_WEIGHT_EXTRABOLD = 800 +50,
+ TTF_WEIGHT_BLACK = 900 +50
+ };
+
+ bool status=FT_New_Face(itsFt.library, QFile::encodeName(file), 0, &itsFt.face) ? false : true;
+
+ if(status)
+ itsFt.open=true;
+
+ PS_FontInfoRec t1info;
+
+ if(0==FT_Get_PS_Font_Info(itsFt.face, &t1info))
+ {
+ itsFamily=t1info.family_name;
+ itsType=TYPE_1;
+ }
+ else
+ {
+ itsFamily=getName(itsFt.face, TT_NAME_ID_FONT_FAMILY);
+ itsType=TRUE_TYPE;
+ }
+
+ if(itsFamily.isEmpty())
+ itsFamily=FT_Get_Postscript_Name(itsFt.face);
+
+ if(itsFamily.isEmpty())
+ status=false; // Hmm... couldn't find any of the names!
+
+ if(status)
+ {
+ removeSymbols(itsFamily);
+ itsPsName=(FT_Get_Postscript_Name(itsFt.face));
+
+ if(TYPE_1==itsType)
+ {
+ itsWeight=strToWeight(t1info.weight);
+ itsItalic=t1info.italic_angle <= -4 || t1info.italic_angle >= 4 ? ITALIC_ITALIC : ITALIC_NONE;
+ }
+ else // TrueType...
+ {
+ TT_Postscript *post=NULL;
+ TT_OS2 *os2=NULL;
+ TT_Header *head=NULL;
+ bool gotItalic=false;
+
+ if(NULL==(os2=(TT_OS2 *)FT_Get_Sfnt_Table(itsFt.face, ft_sfnt_os2)) || 0xFFFF==os2->version)
+ itsWeight=WEIGHT_UNKNOWN;
+ else
+ {
+ FT_UShort weight=(os2->usWeightClass>0 && os2->usWeightClass<100) ? os2->usWeightClass*100 : os2->usWeightClass;
+
+ if(weight<TTF_WEIGHT_THIN)
+ itsWeight=WEIGHT_THIN;
+ else if(weight<TTF_WEIGHT_EXTRALIGHT)
+ itsWeight=WEIGHT_EXTRA_LIGHT;
+ else if(weight<TTF_WEIGHT_LIGHT)
+ itsWeight=WEIGHT_LIGHT;
+ else if(/*weight<TTF_WEIGHT_NORMAL || */ weight<TTF_WEIGHT_MEDIUM)
+ itsWeight=WEIGHT_MEDIUM;
+ else if(weight<TTF_WEIGHT_SEMIBOLD)
+ itsWeight=WEIGHT_SEMI_BOLD;
+ else if(weight<TTF_WEIGHT_BOLD)
+ itsWeight=WEIGHT_BOLD;
+ else if(weight<TTF_WEIGHT_EXTRABOLD)
+ itsWeight=WEIGHT_EXTRA_BOLD;
+ else if(weight<TTF_WEIGHT_BLACK)
+ itsWeight=WEIGHT_BLACK;
+ else if(os2->fsSelection&(1 << 5))
+ itsWeight=WEIGHT_BOLD;
+ else
+ itsWeight=WEIGHT_UNKNOWN;
+
+ itsItalic=os2->fsSelection&(1 << 0) ? ITALIC_ITALIC : ITALIC_NONE;
+ gotItalic=true;
+ }
+
+ if(WEIGHT_UNKNOWN==itsWeight)
+ itsWeight=NULL!=(head=(TT_Header *)FT_Get_Sfnt_Table(itsFt.face, ft_sfnt_head)) && head->Mac_Style & 1
+ ? WEIGHT_BOLD
+ : WEIGHT_MEDIUM;
+
+ if(!gotItalic && (head!=NULL || NULL!=(head=(TT_Header *)FT_Get_Sfnt_Table(itsFt.face, ft_sfnt_head))))
+ {
+ gotItalic=true;
+ itsItalic=head->Mac_Style & 2 ? ITALIC_ITALIC: ITALIC_NONE;
+ }
+
+ if(!gotItalic && NULL!=(post=(TT_Postscript *)FT_Get_Sfnt_Table(itsFt.face, ft_sfnt_post)))
+ {
+ struct TFixed
+ {
+ TFixed(unsigned long v) : upper(v>>16), lower(v&0xFFFF) {}
+
+ short upper,
+ lower;
+
+ float value() { return upper+(lower/65536.0); }
+ };
+
+ gotItalic=true;
+ itsItalic=0.0f==((TFixed)post->italicAngle).value() ? ITALIC_NONE : ITALIC_ITALIC;
+ }
+ }
+ }
+
+ if(!status)
+ closeFaceFt();
+
+ return status;
+}
+
+void CFontEngine::closeFaceFt()
+{
+ if(itsFt.open)
+ {
+ FT_Done_Face(itsFt.face);
+ itsFt.open=false;
+ }
+}
+
+CFontEngine::TFtData::TFtData()
+ : open(false)
+{
+ if(FT_Init_FreeType(&library))
+ {
+ std::cerr << "ERROR: FreeType2 failed to initialise\n";
+ exit(0);
+ }
+}
+
+CFontEngine::TFtData::~TFtData()
+{
+ FT_Done_FreeType(library);
+}
+
+}
diff --git a/kcontrol/kfontinst/kfontinst/FontEngine.h b/kcontrol/kfontinst/kfontinst/FontEngine.h
new file mode 100644
index 000000000..06218c0ae
--- /dev/null
+++ b/kcontrol/kfontinst/kfontinst/FontEngine.h
@@ -0,0 +1,142 @@
+#ifndef __FONT_ENGINE_H__
+#define __FONT_ENGINE_H__
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : KFI::CFontEngine
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 29/04/2001
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2001, 2002, 2003, 2004
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include <qstring.h>
+#include <qstringlist.h>
+
+namespace KFI
+{
+
+class CFontEngine
+{
+ public:
+
+ enum EType
+ {
+ // These have PS Info / support AFM stuff...
+ TRUE_TYPE,
+ TT_COLLECTION,
+ TYPE_1,
+ NONE
+ };
+
+ enum EWeight
+ {
+ WEIGHT_UNKNOWN=0,
+ WEIGHT_THIN,
+ WEIGHT_ULTRA_LIGHT,
+ WEIGHT_EXTRA_LIGHT,
+ WEIGHT_DEMI,
+ WEIGHT_LIGHT,
+ WEIGHT_BOOK,
+ WEIGHT_MEDIUM,
+ WEIGHT_REGULAR,
+ WEIGHT_SEMI_BOLD,
+ WEIGHT_DEMI_BOLD,
+ WEIGHT_BOLD,
+ WEIGHT_EXTRA_BOLD,
+ WEIGHT_ULTRA_BOLD,
+ WEIGHT_HEAVY,
+ WEIGHT_BLACK
+ };
+
+ enum EItalic
+ {
+ ITALIC_NONE,
+ ITALIC_ITALIC,
+ ITALIC_OBLIQUE
+ };
+
+ private:
+
+ struct TFtData
+ {
+ TFtData();
+ ~TFtData();
+
+ FT_Library library;
+ FT_Face face;
+ bool open;
+ };
+
+ public:
+
+ CFontEngine() : itsType(NONE) { }
+ ~CFontEngine() { closeFont(); }
+
+ static EType getType(const char *fname);
+ static QString weightStr(EWeight w);
+ static QString italicStr(EItalic i) { return ITALIC_NONE==i ? "r" : ITALIC_ITALIC==i ? "i" : "o"; }
+
+ //
+ // General functions - these should be used instead of specfic ones below...
+ //
+ bool openFont(const QString &file, int face=0);
+ void closeFont();
+
+ //
+ const QString & getFamilyName() { return itsFamily; }
+ const QString & getPsName() { return itsPsName; }
+ EWeight getWeight() { return itsWeight; }
+ EItalic getItalic() { return itsItalic; }
+ EType getType() { return itsType; }
+ int getNumFaces() { return itsFt.open ? itsFt.face->num_faces : 1; }
+ bool hasPsInfo() { return itsType!=NONE; }
+
+ static EWeight strToWeight(const char *str);
+
+ private:
+
+ bool openFontFt(const QString &file);
+ void closeFaceFt();
+
+ private:
+
+ EWeight itsWeight;
+ EType itsType;
+ EItalic itsItalic;
+ QString itsFamily,
+ itsPsName,
+ itsPath;
+ int itsNumFaces,
+ itsFaceIndex; // Only for TTC fonts - at the moment...
+ TFtData itsFt;
+};
+
+}
+
+#endif
diff --git a/kcontrol/kfontinst/kfontinst/Fontmap.cpp b/kcontrol/kfontinst/kfontinst/Fontmap.cpp
new file mode 100644
index 000000000..0f8178dee
--- /dev/null
+++ b/kcontrol/kfontinst/kfontinst/Fontmap.cpp
@@ -0,0 +1,596 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Namespae : KFI::Fontmap
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 06/06/2003
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2003, 2004
+////////////////////////////////////////////////////////////////////////////////
+
+#include "Fontmap.h"
+#include "FontEngine.h"
+#include "XConfig.h"
+#include "FcEngine.h"
+#include "KfiConstants.h"
+#include <ksavefile.h>
+#include <qtextstream.h>
+#include <qdir.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <qregexp.h>
+#include <fstream>
+#include <unistd.h>
+
+using namespace std;
+
+static const char * findSpace(const char *str)
+{
+ while(str && *str!=' ' && *str!='\t')
+ str++;
+
+ return str;
+}
+
+static bool parseLine(const char *line, QString &ps, QString &fname, bool &isAlias)
+{
+ static const int constMaxLen = 127;
+ static const int constFileMaxLen = 1023;
+
+ //
+ // Format:
+ // "/<psname> (<filename>) ; "
+ // "/<psname> /real ; "
+
+ char a[constMaxLen+1],
+ b[constFileMaxLen+1];
+
+ const char *slash1=strchr(line, '/'),
+ *space1=slash1 ? findSpace(slash1) : NULL, //strchr(slash1, ' ') : NULL,
+ *ob=slash1 ? strchr(slash1, '(') : NULL,
+ *cb=ob ? strchr(ob, ')') : NULL,
+ *slash2=space1 && !ob && !cb ? strchr(space1, '/') : NULL,
+ *space2=slash2 ? findSpace(slash2) : NULL, // strchr(slash2, ' ') : NULL,
+ *semic=cb || space2 ? strchr(cb ? cb : space2, ';') : NULL;
+
+ if(semic && space1-slash1<constMaxLen)
+ {
+ slash1++;
+ memcpy(a, slash1, space1-slash1);
+ a[space1-slash1]='\0';
+
+ if(cb && cb-ob<constFileMaxLen) // Then found a file entry...
+ {
+ ob++;
+ memcpy(b, ob, cb-ob);
+ b[cb-ob]='\0';
+ ps=a;
+ fname=b;
+ isAlias=false;
+ return true;
+ }
+ else if(space2 && space2-slash2<constMaxLen) // Then found an alias...
+ {
+ slash2++;
+ memcpy(b, slash2, space2-slash2);
+ b[space2-slash2]='\0';
+ ps=a;
+ fname=b;
+ isAlias=true;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+//
+// Returns a PS name from an X family name...
+// e.g. "Times New Roman" -> "TimesNewRoman"
+static QString createX11PsName(const QString &font)
+{
+ QString newName(font);
+ unsigned int ch;
+ bool newWord=true;
+
+ newName.replace(QRegExp("\\-"), "_");
+
+ for(ch=0; ch<newName.length(); ++ch)
+ {
+ if(newName[ch].isSpace())
+ newWord=true;
+ else
+ {
+ if(newName[ch]==newName[ch].upper())
+ {
+ if(!newWord)
+ newName[ch]=newName[ch].lower();
+ }
+ else
+ if(newName[ch]==newName[ch].lower())
+ {
+ if(newWord)
+ newName[ch]=newName[ch].upper();
+ }
+ newWord=false;
+ }
+ }
+
+ newName.replace(" ", QString::null);
+ return newName;
+}
+
+static const char * getItalicStr(KFI::CFontEngine::EItalic it)
+{
+ switch(it)
+ {
+ default:
+ case KFI::CFontEngine::ITALIC_NONE:
+ return NULL;
+ case KFI::CFontEngine::ITALIC_ITALIC:
+ return "Italic";
+ case KFI::CFontEngine::ITALIC_OBLIQUE:
+ return "Oblique";
+ }
+}
+
+//
+// Create a full Ps name
+static QString createName(const QString &family, const QString &weight, const char *italic)
+{
+ QString name;
+ QTextOStream str(&name);
+
+ str << family;
+ if(!weight.isEmpty() || NULL!=italic)
+ {
+ str << '-';
+ if(!weight.isEmpty())
+ str << weight;
+ if(NULL!=italic)
+ str << italic;
+ }
+
+ return name;
+}
+
+static QString getEntry(QStringList &list, const QString &name)
+{
+ QStringList::Iterator it(list.begin()),
+ end(list.end());
+
+ for( ; it!=end; ++it)
+ if(0==(*it).find('/'+name+' '))
+ return *it;
+
+ return QString::null;
+}
+
+inline bool isAlias(const QString &entry)
+{
+ return -1==entry.findRev(QRegExp(")\\s*;\\s*$"));
+}
+
+static void addEntry(QStringList &list, const QString &name, const QString &file, const QString &fmapDir)
+{
+ QString existing(getEntry(list, name));
+ bool insert=true;
+
+ if(!existing.isEmpty())
+ if(isAlias(existing))
+ list.remove(existing);
+ else
+ insert=false;
+
+ if(insert)
+ {
+ QString entry;
+ QTextOStream str(&entry);
+
+ str << '/' << name << " (";
+
+ if(0==file.find(fmapDir))
+ str << file.mid(fmapDir.length());
+ else
+ str << file;
+
+ str << ") ;";
+ list.append(entry);
+ }
+}
+
+static void addAliasEntry(QStringList &list, const QString &x11Name, const QString &psName)
+{
+ if(x11Name!=psName)
+ {
+ QString existing(getEntry(list, x11Name));
+
+ if(existing.isEmpty())
+ {
+ QString entry;
+ QTextOStream str(&entry);
+
+ str << '/' << x11Name << " /" << psName << " ;";
+ list.append(entry);
+ }
+ }
+}
+
+static QString locateFile(const char *dir, const char *file, int level=0)
+{
+ if(level<5)
+ {
+ QDir d(dir);
+
+ if(d.isReadable())
+ {
+ const QFileInfoList *fList=d.entryInfoList();
+
+ if(fList)
+ {
+ QFileInfoListIterator it(*fList);
+ QFileInfo *fInfo;
+ QString str;
+
+ for(; NULL!=(fInfo=it.current()); ++it)
+ if("."!=fInfo->fileName() && ".."!=fInfo->fileName())
+ if(fInfo->isDir())
+ {
+ if(!(str=locateFile(QFile::encodeName(fInfo->filePath()+"/"), file, level+1)).isEmpty())
+ return str;
+ }
+ else
+ if(fInfo->fileName()==file)
+ return fInfo->filePath();
+ }
+ }
+ }
+
+ return QString::null;
+}
+
+static QString locateFile(const char *file, const char **dirs)
+{
+ int d;
+ QString str;
+
+ for(d=0; dirs[d]; ++d)
+ if(!(str=locateFile(dirs[d], file)).isEmpty())
+ return str;
+
+ return QString::null;
+}
+
+#define FONTMAP "Fontmap"
+
+namespace KFI
+{
+
+namespace Fontmap
+{
+
+bool create(const QString &dir, CFontEngine &fe)
+{
+ bool root(Misc::root()),
+ added=false;
+ QString fmapDir(Misc::dirSyntax(root ? KFI_ROOT_CFG_DIR : dir));
+ CFile old(fmapDir);
+ QStringList entries;
+ int i;
+ FcPattern *pat = FcPatternCreate();
+ FcObjectSet *os = FcObjectSetBuild(FC_FILE, FC_SCALABLE, (void*)0);
+ FcFontSet *fs = FcFontList(0, pat, os);
+
+ FcPatternDestroy(pat);
+ FcObjectSetDestroy(os);
+
+ for (i = 0; i<fs->nfont; i++)
+ {
+ QString fName(Misc::fileSyntax(CFcEngine::getFcString(fs->fonts[i], FC_FILE)));
+ FcBool scalable=FcFalse;
+
+ if(!fName.isEmpty() && (root || dir.isEmpty() || 0==fName.find(dir)) &&
+ FcResultMatch==FcPatternGetBool(fs->fonts[i], FC_SCALABLE, 0, &scalable) && scalable)
+ {
+ const QStringList *existing=old.getEntries(fName);
+
+ if(existing && existing->count())
+ entries+=(*existing);
+ else
+ {
+ int face=0,
+ numFaces=0;
+
+ do
+ {
+ if(fe.openFont(fName, face))
+ {
+ if(fe.hasPsInfo())
+ {
+ if(0==numFaces)
+ numFaces=fe.getNumFaces(); // Only really for TTC files...
+
+ //
+ // Add real
+ addEntry(entries, fe.getPsName(), fName, fmapDir);
+ added=true;
+
+ //
+ // Add fake entries for X11 generated names
+ switch(fe.getWeight())
+ {
+ case CFontEngine::WEIGHT_MEDIUM:
+ case CFontEngine::WEIGHT_REGULAR:
+ {
+ QString x11Ps(createX11PsName(fe.getFamilyName()));
+
+ if(CFontEngine::ITALIC_ITALIC!=fe.getItalic() &&
+ CFontEngine::ITALIC_OBLIQUE!=fe.getItalic())
+ addAliasEntry(entries,
+ createName(x11Ps, "Roman",
+ getItalicStr(fe.getItalic())),
+ fe.getPsName());
+ addAliasEntry(entries,
+ createName(x11Ps, NULL, getItalicStr(fe.getItalic())),
+ fe.getPsName());
+ break;
+ }
+ case CFontEngine::WEIGHT_UNKNOWN:
+ break;
+ default:
+ addAliasEntry(entries,
+ createName(createX11PsName(fe.getFamilyName()),
+ CFontEngine::weightStr(fe.getWeight()),
+ getItalicStr(fe.getItalic())),
+ fe.getPsName());
+ }
+ }
+ fe.closeFont();
+ }
+ }
+ while(++face<numFaces);
+ }
+ }
+ }
+
+ bool status=true;
+
+ if(added || entries.count()!=old.getLineCount())
+ {
+ KSaveFile out(fmapDir+FONTMAP);
+ QTextStream *stream=out.textStream();
+
+ if(stream)
+ {
+ QStringList::Iterator it;
+
+ for(it=entries.begin(); it!=entries.end(); ++it)
+ *stream << *it << endl;
+ }
+ else
+ status=false;
+ }
+
+ //
+ // Ensure GS's main Fontmap references our file...
+ if(root && status)
+ {
+ static const char * constGhostscriptDirs[]=
+ {
+ "/usr/share/ghostscript/",
+ "/usr/local/share/ghostscript/",
+ "/usr/share/gs-esp/",
+ NULL
+ };
+
+ QString gsFile=locateFile(FONTMAP, constGhostscriptDirs);
+
+ if(!gsFile.isEmpty())
+ {
+ const int constMaxLineLen=1024;
+ const char *constRLF=".runlibfile";
+
+ char line[constMaxLineLen];
+ ifstream in(QFile::encodeName(gsFile));
+
+ if(in)
+ {
+ QCString fmap(QFile::encodeName(fmapDir+FONTMAP));
+ int lineNum=0,
+ kfiLine=-1,
+ gsLine=-1,
+ ncLine=-1;
+
+ do
+ {
+ in.getline(line, constMaxLineLen);
+
+ if(in.good())
+ {
+ line[constMaxLineLen-1]='\0';
+
+ if(strstr(line, fmap.data())!=NULL && strstr(line, constRLF)!=NULL)
+ kfiLine=lineNum;
+ else if(strstr(line, FONTMAP".GS")!=NULL && strstr(line, constRLF)!=NULL)
+ gsLine=lineNum;
+ if(-1==ncLine && '%'!=line[0])
+ ncLine=lineNum;
+ lineNum++;
+ }
+ }
+ while(!in.eof() && (-1==kfiLine || -1==gsLine));
+
+ //
+ // If the file doesn't already say to use our Fontmap file, then tell it to!
+ // Also, ensure ours is .runlibfile'd before the main GS one - else problems can occur
+ if(-1==kfiLine || kfiLine>gsLine)
+ {
+ in.clear();
+ in.seekg(0, ios::end);
+ int size= (streamoff) in.tellg();
+ in.seekg(0, ios::beg);
+
+ char *buffer=new char[size+strlen(fmap)+strlen(constRLF)+5];
+
+ if(buffer)
+ {
+ bool added=false;
+
+ buffer[0]='\0';
+ lineNum=0;
+
+ do
+ {
+ in.getline(line, constMaxLineLen);
+
+ if(in.good())
+ {
+ line[constMaxLineLen-1]='\0';
+
+ if(lineNum>=ncLine && !added)
+ {
+ strcat(buffer, "(");
+ strcat(buffer, fmap);
+ strcat(buffer, ") ");
+ strcat(buffer, constRLF);
+ strcat(buffer, "\n");
+ added=true;
+ }
+
+ if(lineNum!=kfiLine)
+ {
+ strcat(buffer, line);
+ strcat(buffer, "\n");
+ }
+ lineNum++;
+ }
+ }
+ while(!in.eof());
+
+ in.close();
+
+ if(added) // Don't re-write GS's Fontmap unless we've actually added something...
+ {
+ KSaveFile out(gsFile);
+ QTextStream *stream=out.textStream();
+
+ if(stream)
+ *stream << buffer;
+ }
+ delete [] buffer;
+ }
+ }
+ }
+ }
+ }
+
+ return status;
+}
+
+CFile::CFile(const QString &dir)
+ : itsDir(dir),
+ itsLineCount(0)
+{
+ ifstream f(QFile::encodeName(dir+FONTMAP));
+
+ itsEntries.setAutoDelete(true);
+
+ if(f)
+ {
+ static const int constMaxLine=512;
+
+ char line[constMaxLine+1];
+ TEntry *current=NULL;
+
+ while(!f.eof())
+ {
+ f.getline(line, constMaxLine);
+
+ if(!f.eof())
+ {
+ QString ps,
+ fname;
+ bool isAlias;
+
+ if(parseLine(line, ps, fname, isAlias))
+ {
+ itsLineCount++;
+
+ TEntry *entry=getEntry(&current, fname, isAlias);
+
+ if(!isAlias && entry && entry->psName.isEmpty())
+ entry->psName=ps;
+
+ if(entry)
+ entry->entries.append(line);
+ }
+ }
+ }
+ f.close();
+ }
+}
+
+const QStringList * CFile::getEntries(const QString &fname)
+{
+ TEntry *entry=findEntry(0==fname.find(itsDir) ? fname.mid(itsDir.length()) : fname, false);
+
+ return entry ? &entry->entries : NULL;
+}
+
+CFile::TEntry * CFile::findEntry(const QString &fname, bool isAlias)
+{
+ TEntry *entry=NULL;
+
+ for(entry=itsEntries.first(); entry; entry=itsEntries.next())
+ if(isAlias ? entry->psName==fname : entry->filename==fname)
+ break;
+
+ return entry;
+}
+
+CFile::TEntry * CFile::getEntry(TEntry **current, const QString &fname, bool isAlias)
+{
+ //
+ // See if its the current one...
+ if(*current && (isAlias ? (*current)->psName==fname : (*current)->filename==fname))
+ return *current;
+
+ //
+ // See if its already known...
+ TEntry *entry=findEntry(fname, isAlias);
+
+ //
+ // If not found, then create a new entry
+ if(!entry)
+ {
+ entry=new TEntry(fname);
+ itsEntries.append(entry);
+ }
+
+ *current=entry;
+ return entry;
+}
+
+}
+
+}
diff --git a/kcontrol/kfontinst/kfontinst/Fontmap.h b/kcontrol/kfontinst/kfontinst/Fontmap.h
new file mode 100644
index 000000000..28d5c9d7e
--- /dev/null
+++ b/kcontrol/kfontinst/kfontinst/Fontmap.h
@@ -0,0 +1,79 @@
+#ifndef __FONTMAP_H__
+#define __FONTMAP_H__
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Namespace : KFI::Fontmap
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 06/06/2003
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2003, 2004
+////////////////////////////////////////////////////////////////////////////////
+
+#include <qstring.h>
+#include <qstringlist.h>
+
+namespace KFI
+{
+
+class CFontEngine;
+
+namespace Fontmap
+{
+ class CFile
+ {
+ private:
+
+ struct TEntry
+ {
+ TEntry(const QString &fname) : filename(fname) {}
+
+ QString filename,
+ psName;
+ QStringList entries;
+ };
+
+ public:
+
+ CFile(const QString &dir);
+
+ const QStringList * getEntries(const QString &fname);
+ unsigned int getLineCount() { return itsLineCount; }
+
+ private:
+
+ TEntry * findEntry(const QString &fname, bool isAlias=false);
+ TEntry * getEntry(TEntry **current, const QString &fname, bool isAlias=false);
+
+ private:
+
+ QString itsDir;
+ QPtrList<TEntry> itsEntries;
+ unsigned int itsLineCount;
+ };
+
+ extern bool create(const QString &dir, CFontEngine &fe);
+}
+
+}
+
+#endif
diff --git a/kcontrol/kfontinst/kfontinst/GetPid.c b/kcontrol/kfontinst/kfontinst/GetPid.c
new file mode 100644
index 000000000..015ea7ce9
--- /dev/null
+++ b/kcontrol/kfontinst/kfontinst/GetPid.c
@@ -0,0 +1,519 @@
+/*
+////////////////////////////////////////////////////////////////////////////////
+//
+// File Name : GetPid.c
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 19/03/2003
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2003
+////////////////////////////////////////////////////////////////////////////////
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(__DragonFly__)
+#include <sys/param.h>
+#endif
+
+#include <sys/types.h>
+
+#ifndef __cplusplus
+#define bool unsigned int
+#define false 0
+#define true (!false)
+#endif
+
+#define BUFSIZE 1024
+#define PROCDIR "/proc"
+
+/*
+ Get process ID - using name of exe and parent process ID
+
+ Implemented for:
+
+ Linux Tested on Linux 2.4
+ FreeBSD Tested on FreeBSD 5.1 by Brian Ledbetter <brian@shadowcom.net>
+ NetBSD
+ Irix
+ Solaris Tested on Solaris 8 x86 by Torsten Kasch <tk@Genetik.Uni-Bielefeld.DE>
+ HP-UX Tested on HP-UX B.11.11 U 9000/800
+ AIX
+ ...else parse output of "ps -eaf"
+
+
+ Some sections of this code are copied from / inspired by ksysguard,
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ To test this file, do the following:
+
+ 1. Compile this file as follows:
+
+ gcc GetPid.c -DTEST_GETPID -DOS_Linux -o tst
+
+ ...replace OS_Linux with your particular OS type: OS_FreeBSD, OS_NetBSD, OS_Irix, OS_Solaris,
+ OS_HPUX, or OS_AIX
+
+ 2. Start a program - such as "vi"
+ 3. Do a "ps -eaf" to ensure there is *only one* process called "vi"
+ 4. Get the parent process ID of your "vi" above
+ 5. Call tst with that value -e.g. vi ppid=23 then ./tst vi 23
+ ...this should then print out the process ID of "vi"
+ 6. Email me and let me know if it works!
+*/
+
+#if defined OS_Linux || defined __Linux__
+
+#include <dirent.h>
+#include <ctype.h>
+
+#define FOUND_NAME 1
+#define FOUND_PPID 2
+#define FOUND_ALL (FOUND_NAME+FOUND_PPID)
+
+unsigned int kfi_getPid(const char *proc, unsigned int ppid)
+{
+ bool error=false;
+ unsigned int pid=0;
+ DIR *dir;
+ struct dirent *entry;
+
+ /* read in current process list via the /proc filesystem entry */
+ if(NULL!=(dir=opendir(PROCDIR)))
+ {
+ while((entry=readdir(dir)) && !error)
+ if(isdigit(entry->d_name[0]))
+ {
+ char buf[BUFSIZE];
+ FILE *fd;
+
+ snprintf(buf, BUFSIZE-1, PROCDIR"/%d/status", atoi(entry->d_name));
+
+ if(NULL!=(fd=fopen(buf, "r")))
+ {
+ char format[32],
+ tagformat[32],
+ tag[32],
+ name[64];
+ int found=0;
+
+ found=0;
+ sprintf(format, "%%%d[^\n]\n", (int) sizeof(buf) - 1);
+ sprintf(tagformat, "%%%ds", (int) sizeof(tag) - 1);
+ for(;found<FOUND_ALL;)
+ {
+ if (fscanf(fd, format, buf)!=1)
+ break;
+ buf[sizeof(buf)-1]='\0';
+ sscanf(buf, tagformat, tag);
+ tag[sizeof(tag) - 1] = '\0';
+ if(0==strcmp(tag, "Name:"))
+ {
+ sscanf(buf, "%*s %63s", name);
+ if(NULL==name || 0!=strcmp(name, proc))
+ break;
+ found|=FOUND_NAME;
+ }
+ else if(0==strcmp(tag, "PPid:"))
+ {
+ unsigned int proc_ppid;
+
+ sscanf(buf, "%*s %u", &proc_ppid);
+ if(ppid!=proc_ppid)
+ break;
+ found|=FOUND_PPID;
+ }
+ }
+ if(FOUND_ALL==found)
+ {
+ if(pid)
+ error=true;
+ else
+ pid=atoi(entry->d_name);
+ }
+ fclose(fd);
+ }
+ }
+ closedir(dir);
+ }
+
+ return error ? 0 : pid;
+}
+
+#elif defined OS_FreeBSD || defined OS_NetBSD || defined __FreeBSD__ || defined __NetBSD__ || defined OS_Darwin
+
+#include <ctype.h>
+#include <dirent.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <sys/param.h>
+#if __FreeBSD_version > 500015
+#include <sys/priority.h>
+#endif
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/user.h>
+#include <unistd.h>
+unsigned int kfi_getPid(const char *proc, unsigned int ppid)
+{
+ bool error=false;
+ unsigned int pid=0;
+ int mib[4];
+ size_t len,
+ num;
+ struct kinfo_proc *p;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_ALL;
+ sysctl(mib, 3, NULL, &len, NULL, 0);
+ p=(struct kinfo_proc*)malloc(len);
+ sysctl(mib, 3, p, &len, NULL, 0);
+
+ for(num=0; num < len / sizeof(struct kinfo_proc) && !error; num++)
+ {
+ struct kinfo_proc proc_p;
+ size_t len;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+#if __FreeBSD_version >= 500015
+ mib[3] = p[num].ki_pid;
+#elif defined(__DragonFly__) && __DragonFly_version >= 190000
+ mib[3] = p[num].kp_pid;
+#else
+ mib[3] = p[num].kp_proc.p_pid;
+#endif
+
+ len=sizeof(proc_p);
+ if(-1==sysctl(mib, 4, &proc_p, &len, NULL, 0) || !len)
+ break;
+ else
+ {
+#if __FreeBSD_version >= 500015
+ if(proc_p.ki_ppid==ppid && p[num].ki_comm && 0==strcmp(p[num].ki_comm, proc))
+ if(pid)
+ error=true;
+ else
+ pid=p[num].ki_pid;
+#elif defined (__DragonFly__) && __DragonFly_version >= 190000
+ if(proc_p.kp_ppid==ppid && p[num].kp_comm && 0==strcmp(p[num].kp_comm, proc))
+ if(pid)
+ error=true;
+ else
+ pid=p[num].kp_pid;
+#else
+#if defined(__DragonFly__)
+ if(proc_p.kp_eproc.e_ppid==ppid && p[num].kp_thread.td_comm && 0==strcmp(p[num].kp_thread.td_comm, proc))
+#else
+ if(proc_p.kp_eproc.e_ppid==ppid && p[num].kp_proc.p_comm && 0==strcmp(p[num].kp_proc.p_comm, proc))
+#endif
+ if(pid)
+ error=true;
+ else
+ pid=p[num].kp_proc.p_pid;
+#endif
+ }
+ }
+ free(p);
+
+ return error ? 0 : pid;
+}
+
+#elif defined OS_Irix || defined OS_Solaris
+
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <dirent.h>
+#include <pwd.h>
+#include <sys/resource.h>
+#ifdef OS_Solaris
+
+#if (!defined(_LP64)) && (_FILE_OFFSET_BITS - 0 == 64)
+#define PROCFS_FILE_OFFSET_BITS_HACK 1
+#undef _FILE_OFFSET_BITS
+#else
+#define PROCFS_FILE_OFFSET_BITS_HACK 0
+#endif
+
+#include <procfs.h>
+
+#if (PROCFS_FILE_OFFSET_BITS_HACK - 0 == 1)
+#define _FILE_OFFSET_BITS 64
+#endif
+
+#else
+#include <sys/procfs.h>
+#include <sys/sysmp.h>
+#endif
+#include <sys/sysinfo.h>
+
+unsigned int kfi_getPid(const char *proc, pid_t ppid)
+{
+ DIR *procdir;
+ bool error=false;
+ pid_t pid=(pid_t)0;
+
+ if(NULL!=(procdir=opendir(PROCDIR)))
+ {
+ struct dirent *de;
+
+ rewinddir(procdir);
+ while((de=readdir(procdir)) && !error)
+ if('.'==de->d_name[0])
+ continue;
+ else
+ {
+ int fd;
+ char buf[BUFSIZE];
+#ifdef OS_Solaris
+ psinfo_t psinfo;
+
+ snprintf(buf, BUFSIZE - 1, "%s/%s/psinfo", PROCDIR, de->d_name);
+#else
+ prpsinfo_t psinfo;
+
+ sprintf(buf, PROCDIR"/pinfo/%ld", pid);
+#endif
+
+ if((fd=open(buf, O_RDONLY))<0)
+ continue;
+
+#ifdef OS_Solaris
+ if(sizeof(psinfo_t)!=read(fd, &psinfo, sizeof(psinfo_t)))
+#else
+ if(ioctl(fd, PIOCPSINFO, &psinfo)<0)
+#endif
+ {
+ close(fd);
+ continue;
+ }
+ close(fd);
+
+ if(psinfo.pr_ppid==ppid && psinfo.pr_fname && 0==strcmp(psinfo.pr_fname, proc))
+ if(pid)
+ error=true;
+ else
+ pid=psinfo.pr_pid;
+ }
+ closedir(procdir);
+ }
+
+ return error ? 0 : pid;
+}
+
+#elif defined OS_HPUX
+
+#include <sys/pstat.h>
+#define MAX_PROCS 50
+
+unsigned int kfi_getPid(const char *proc, unsigned int ppid)
+{
+ bool error=false;
+ unsigned int pid=0;
+ int i,
+ count,
+ idx=0;
+ struct pst_status pst[MAX_PROCS];
+
+ while((count=pstat_getproc(&pst[0], sizeof(pst[0]), MAX_PROCS, idx)) > 0 && !error)
+ {
+ for (i = 0; i<count && !error; i++)
+ if(pst[i].pst_ppid==ppid && pst[i].pst_ucomm && 0==strcmp(pst[i].pst_ucomm, proc))
+ if(pid)
+ error=true;
+ else
+ pid=pst[i].pst_pid;
+
+ idx=pst[count-1].pst_idx+1;
+ }
+
+ return error ? 0 : pid;
+}
+
+#elif defined OS_AIX
+
+#include <procinfo.h>
+#define MAX_PROCS 50
+
+unsigned int kfi_getPid(const char *proc, unsigned int ppid)
+{
+ bool error=false;
+ unsigned int pid=0;
+ int i,
+ count,
+ idx=0;
+ struct procsinfo pi[MAX_PROCS];
+
+ while((count=getprocs(&pi, sizeof(pi[0]), 0, 0, &pid, 1)) >0 && !error)
+ {
+ for (i = 0; i<count && !error; i++)
+ if(pi[i].pi_ppid==ppid && pi[i].pi_comm && 0==strcmp(pi[i].pi_comm, proc))
+ if(pid)
+ error=true;
+ else
+ pid=pi[i].pi_pid;
+
+ idx=pi[count-1].pi_idx+1;
+ }
+
+ return error ? 0 : pid;
+}
+
+#else
+#warning "Unable to determine operating system version! This may cause the getPid() function to fail at random!"
+
+/* Default to reading "ps -eaf" output */
+
+#include <pwd.h>
+#include <limits.h>
+#include <ctype.h>
+
+#define FOUND_PID 1
+#define FOUND_PPID 2
+#define FOUND_CMD 4
+#define FOUND_ALL (FOUND_PID+FOUND_PPID+FOUND_CMD)
+
+static int checkCmd(const char *proc, const char *cmd)
+{
+ int len=(int)strlen(cmd),
+ ch;
+
+ if(len>1)
+ for(ch=len-2; ch>=0; --ch)
+ if('/'==cmd[ch])
+ return strcmp(proc, &cmd[ch+1]);
+
+ return strcmp(proc, cmd);
+}
+
+unsigned int kfi_getPid(const char *proc, unsigned int ppid)
+{
+ bool error=false;
+ unsigned int pid=0;
+ static int pid_c=-1,
+ ppid_c=-1,
+ time_c=-1,
+ cmd_c=-1;
+
+ char cmd[BUFSIZE+1];
+ FILE *p;
+
+ /* If this function has been run before, and we know the column positions, then we can grep for just our command */
+ if(-1!=pid_c && -1!=ppid_c && -1!=time_c && -1!=cmd_c)
+ snprintf(cmd, BUFSIZE, "ps -eaf | grep %s", proc);
+ else
+ strcpy(cmd, "ps -eaf");
+
+ if(NULL!=(p=popen(cmd, "r")))
+ {
+ char line[BUFSIZE+1];
+ int c=0;
+ char *linep=NULL,
+ *token=NULL;
+
+ /* Read 1st line to determine columns... */
+ if((-1==pid_c || -1==ppid_c || -1==time_c || -1==cmd_c) && NULL!=fgets(line, BUFSIZE, p))
+ {
+ for(linep=line; -1==pid_c || -1==ppid_c || -1==time_c || -1==cmd_c; linep=NULL)
+ if(NULL!=(token=strtok(linep, " \t\n")))
+ {
+ if(0==strcmp("PID", token))
+ pid_c=c;
+ else if(0==strcmp("PPID", token))
+ ppid_c=c;
+ else if(NULL!=strstr("TIME", token))
+ time_c=c;
+ else if(0==strcmp("COMMAND", token) || 0==strcmp("CMD", token))
+ cmd_c=c;
+ c++;
+ }
+ else
+ break;
+ }
+
+ /* If all column headings read, then look for details... */
+ if(-1!=pid_c && -1!=ppid_c && -1!=time_c && -1!=cmd_c)
+ while(NULL!=fgets(line, BUFSIZE, p) && !error)
+ {
+ int found=0,
+ ps_pid=0,
+ offset=0;
+
+ c=0;
+ for(linep=line; FOUND_ALL!=found; linep=NULL)
+ if(NULL!=(token=strtok(linep, " \t\n")))
+ {
+ if(c==pid_c)
+ {
+ found|=FOUND_PID;
+ ps_pid=atoi(token);
+ }
+ else if(c==ppid_c)
+ {
+ if(((unsigned int)atoi(token))!=ppid)
+ break;
+ found|=FOUND_PPID;
+ }
+ else if(c==time_c)
+ offset=isdigit(token[0]) ? 0 : 1;
+ else if(c==(cmd_c+offset))
+ {
+ if(0!=checkCmd(proc, token))
+ break;
+ found|=FOUND_CMD;
+ }
+ c++;
+ }
+ else
+ break;
+
+ if(FOUND_ALL==found)
+ {
+ if(pid)
+ error=true;
+ else
+ pid=ps_pid;
+ }
+ }
+ pclose(p);
+ }
+
+ return error ? 0 : pid;
+}
+
+#endif
+
+#ifdef TEST_GETPID
+int main(int argc, char *argv[])
+{
+ if(3==argc)
+ printf("PID %u\n", kfi_getPid(argv[1], atoi(argv[2])));
+ else
+ printf("Usage: %s <process> <parent-process-id>\n", argv[0]);
+ return 0;
+}
+#endif
diff --git a/kcontrol/kfontinst/kfontinst/Main.cpp b/kcontrol/kfontinst/kfontinst/Main.cpp
new file mode 100644
index 000000000..2da9a8997
--- /dev/null
+++ b/kcontrol/kfontinst/kfontinst/Main.cpp
@@ -0,0 +1,335 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// File Name : Main.cpp
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 20/03/2003
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2003, 2004
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "Misc.h"
+#include "FontEngine.h"
+#include "Fontmap.h"
+#include "XConfig.h"
+#include "kxftconfig.h"
+#include <fontconfig/fontconfig.h>
+#include <qfile.h>
+#include <stdio.h>
+
+//
+// Bug#99335 Solaris 2.6 does not have getopt.h :-(
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+#include <unistd.h>
+#endif
+#include <iostream>
+
+#define KFI_XF86CFG "XF86Config"
+#define KFI_XORGCFG "xorg.conf"
+
+static const char * getFile(const char *entry, const char **posibilities)
+{
+ if(KFI::Misc::fExists(entry))
+ return entry;
+ else
+ {
+ int f;
+
+ for(f=0; posibilities[f]; ++f)
+ if(KFI::Misc::fExists(posibilities[f]))
+ break;
+
+ return posibilities[f];
+ }
+}
+
+static const char * constXConfigFiles[]=
+{
+ "/etc/X11/"KFI_XORGCFG,
+ "/etc/X11/"KFI_XORGCFG"-4",
+ "/etc/"KFI_XORGCFG,
+ "/usr/X11R6/etc/X11/"KFI_XORGCFG,
+ "/usr/X11R6/etc/X11/"KFI_XORGCFG"-4",
+ "/usr/X11R6/lib/X11/"KFI_XORGCFG,
+ "/usr/X11R6/lib/X11/"KFI_XORGCFG"-4",
+
+ "/etc/X11/"KFI_XF86CFG"-4",
+ "/etc/X11/"KFI_XF86CFG,
+ "/etc/"KFI_XF86CFG"-4",
+ "/etc/"KFI_XF86CFG,
+ "/usr/X11R6/etc/X11/"KFI_XF86CFG"-4",
+ "/usr/X11R6/etc/X11/"KFI_XF86CFG,
+ "/usr/X11R6/lib/X11/"KFI_XF86CFG"-4",
+ "/usr/X11R6/lib/X11/"KFI_XF86CFG,
+
+ NULL
+};
+
+static const char * constXfsConfigFiles[]=
+{
+ "/etc/X11/fs/config",
+ "/usr/openwin/lib/X11/fonts/fontserver.cfg",
+ NULL
+};
+
+KFI::CXConfig * getXCfg(bool root)
+{
+ if(root)
+ {
+ //
+ // Try to determine location for X and xfs config files...
+ // ...note on some systems (Solaris and HP-UX) only the xfs file will be found
+ bool xfs=false;
+ KFI::CXConfig *xcfg=NULL;
+ QString xConfigFile=getFile(QFile::encodeName(constXConfigFiles[0]), constXConfigFiles),
+ xfsConfigFile=getFile(QFile::encodeName(constXfsConfigFiles[0]), constXfsConfigFiles);
+
+ // If found xfs, but not X - then assume that xfs is being used...
+ if(!xfsConfigFile.isEmpty() && xConfigFile.isEmpty())
+ xfs=true;
+ else if(!xConfigFile.isEmpty()) // Read xConfig file to determine which one...
+ {
+ xcfg=new KFI::CXConfig(KFI::CXConfig::X11, xConfigFile);
+
+ if(!xfsConfigFile.isEmpty() && xcfg->xfsInPath())
+ {
+ delete xcfg;
+ xfs=true;
+ }
+ }
+
+ // OK, if still set to X11 config, but this mentions fontconfig FPE, then delete - as we're not interested
+ // anymore...
+ if(xcfg && xcfg->fcInPath())
+ delete xcfg;
+
+ return xfs ? new KFI::CXConfig(KFI::CXConfig::XFS, xfsConfigFile) : xcfg;
+ }
+
+ return NULL;
+}
+
+static void usage(char *app)
+{
+ std::cerr << "Usage: " << app << " [OPTIONS]... [FOLDER]..." << std::endl
+ << std::endl
+ << " Helper application for KDE's fonts:/ ioslave." << std::endl
+ << std::endl
+#ifdef HAVE_GETOPT_H
+ << " -x, --configure_x Configure FOLDER for regular x - i.e." << std::endl
+ << " create fonts.dir, fonts.scale and encodngs.dir" << std::endl
+ << std::endl
+ << " -g, --configure_gs Create Fontmap file. If run as root, then " << std::endl
+ << " no paramter is required as all fonts are " << std::endl
+ << " configured, and Fontmap placed in /etc/fonts" << std::endl
+ << " For non-root, fonts located in FOLDER are" << std::endl
+ << " configured, and Fontmap placed there." << std::endl
+ << std::endl
+ << " -f, --add_to_fc_cfg Add FOLDER to fontconfig config files." << std::endl
+ << std::endl
+ << " -a, --add_to_x_cfg Add FOLDER to X config files only when run as root.," << std::endl
+ << std::endl
+ << " -r, --refresh_x Refresh X." << std::endl
+ << std::endl
+ << " -s, --refresh_xfs Refresh Xfs." << std::endl
+#else
+ << " -x Configure FOLDER for regular x - i.e." << std::endl
+ << " create fonts.dir, fonts.scale and encodngs.dir" << std::endl
+ << std::endl
+ << " -g Create Fontmap file. If run as root, then " << std::endl
+ << " no paramter is required as all fonts are " << std::endl
+ << " configured, and Fontmap placed in /etc/fonts" << std::endl
+ << " For non-root, fonts located in FOLDER are" << std::endl
+ << " configured, and Fontmap placed there." << std::endl
+ << std::endl
+ << " -f Add FOLDER to fontconfig config files." << std::endl
+ << std::endl
+ << " -a Add FOLDER to X config files only when run as root.," << std::endl
+ << std::endl
+ << " -r Refresh X." << std::endl
+ << std::endl
+ << " -s Refresh Xfs." << std::endl
+#endif
+ << std::endl
+ << std::endl
+ << " (C) Craig Drummond, 2003, 2004." << std::endl
+ << std::endl;
+
+ exit(-1);
+}
+
+void refresh(bool refreshX, bool refreshXfs, bool root)
+{
+ if(refreshX)
+ KFI::CXConfig::refreshPaths(false);
+ if(refreshXfs && root)
+ KFI::CXConfig::refreshPaths(true);
+}
+
+int main(int argc, char *argv[])
+{
+#ifdef HAVE_GETOPT_H
+ static struct option options[]=
+ {
+ { "configure_x", 0, 0, 'x' },
+ { "configure_gs", 0, 0, 'g' },
+ { "add_to_fc_cfg", 0, 0, 'f' },
+ { "add_to_x_cfg", 0, 0, 'a' },
+ { "refresh_x", 0, 0, 'r' },
+ { "refresh_xfs", 0, 0, 's' },
+ { 0, 0, 0, 0 }
+ };
+#endif
+
+ int c=0,
+ rv=0;
+ bool doX=false,
+ doGs=false,
+ addToX=false,
+ addToFc=false,
+ refreshX=false,
+ refreshXfs=false,
+ root=KFI::Misc::root();
+
+#ifdef HAVE_GETOPT_H
+ int optIndex;
+ while(-1!=(c=getopt_long(argc, argv, "xgfars", options, &optIndex)))
+#else
+ while(-1!=(c=getopt(argc, argv, "xgfars")))
+#endif
+ switch(c)
+ {
+ case 'x':
+ doX=true;
+ break;
+ case 'g':
+ doGs=true;
+ break;
+ case 'f':
+ addToFc=true;
+ break;
+ case 'a':
+ addToX=true;
+ break;
+ case 'r':
+ refreshX=true;
+ break;
+ case 's':
+ refreshXfs=true;
+ break;
+ case '?':
+ usage(argv[0]);
+ break;
+ }
+
+ int left=argc-optind;
+ bool folderRequired=doX || addToX || addToFc || (!root && doGs);
+
+ if (left>1 || (0==left && folderRequired) || (!doX && !doGs && !addToX && !addToFc))
+ usage(argv[0]);
+ else
+ {
+ QString folder;
+
+ if(folderRequired)
+ {
+ folder=argv[optind];
+ unsigned int len=folder.length();
+
+ // Remove quotes...
+ if( (folder[0]==QChar('\'') || folder[0]==QChar('\"')) &&
+ (folder[len-1]==QChar('\'') || folder[len-1]==QChar('\"')))
+ folder=folder.mid(1, len-2);
+ folder=KFI::Misc::dirSyntax(folder);
+ }
+
+ if(folderRequired && !KFI::Misc::dExists(folder))
+ {
+ std::cerr << "ERROR: " << QFile::encodeName(folder) << " does not exist!" << std::endl;
+ rv=-2;
+ }
+ else
+ {
+ if(!folder.isEmpty())
+ {
+ if(0==rv && addToFc)
+ {
+ //
+ // Only add folder to fontconfig's config if its not already there...
+ FcStrList *list=FcConfigGetFontDirs(FcConfigGetCurrent());
+ FcChar8 *dir;
+ bool found=false;
+
+ while((dir=FcStrListNext(list)))
+ if(0==KFI::Misc::dirSyntax((const char *)dir).find(folder))
+ found=true;
+
+ if(!found)
+ {
+ KXftConfig *xft=new KXftConfig(KXftConfig::Dirs, root);
+
+ xft->addDir(folder);
+ rv=xft->apply() ? 0 : -3;
+ delete xft;
+ }
+ }
+
+ if(0==rv && addToX && root)
+ {
+ KFI::CXConfig *x=NULL;
+
+ if((x=getXCfg(true)))
+ {
+ x->addPath(folder);
+ rv=x->writeConfig() ? 0 : -4;
+ delete x;
+ }
+ else
+ rv=-5;
+ }
+ }
+
+ if(0==rv && (doX || doGs))
+ {
+ if(0==rv && doX)
+ rv=KFI::CXConfig::configureDir(folder) ? 0 : -5;
+
+ refresh(refreshX, refreshXfs, root);
+
+ if(0==rv && doGs)
+ {
+ KFI::CFontEngine fe;
+ rv=KFI::Fontmap::create(root ? QString::null : folder, fe) ? 0 : -6;
+ }
+ }
+ else if(0==rv)
+ refresh(refreshX, refreshXfs, root);
+ }
+ }
+
+ return rv;
+}
diff --git a/kcontrol/kfontinst/kfontinst/Makefile.am b/kcontrol/kfontinst/kfontinst/Makefile.am
new file mode 100644
index 000000000..3cfcfa689
--- /dev/null
+++ b/kcontrol/kfontinst/kfontinst/Makefile.am
@@ -0,0 +1,16 @@
+bin_PROGRAMS = kfontinst
+kfontinst_SOURCES = \
+Main.cpp \
+FontEngine.cpp \
+Fontmap.cpp \
+GetPid.c \
+XConfig.cpp
+
+noinst_HEADERS= \
+FontEngine.h \
+Fontmap.h \
+XConfig.h
+
+kfontinst_LDADD = ../../fonts/libkxftconfig.la $(LIBFONTCONFIG_LIBS) $(LIBFREETYPE_LIBS) $(LIBZ) $(LIB_KIO) ../lib/libkfontinst.la
+kfontinst_LDFLAGS = $(all_libraries) $(LIBFONTCONFIG_RPATH) $(LIBFREETYPE_RPATH) $(KDE_RPATH)
+AM_CPPFLAGS= -DOS_$(UNAME) -I$(srcdir)/../lib -I$(srcdir)/../../fonts $(all_includes) $(LIBFREETYPE_CFLAGS) $(LIBFONTCONFIG_CFLAGS)
diff --git a/kcontrol/kfontinst/kfontinst/XConfig.cpp b/kcontrol/kfontinst/kfontinst/XConfig.cpp
new file mode 100644
index 000000000..490c8dfe5
--- /dev/null
+++ b/kcontrol/kfontinst/kfontinst/XConfig.cpp
@@ -0,0 +1,760 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : KFI::CXConfig
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 05/05/2001
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2001, 2002, 2003, 2004
+////////////////////////////////////////////////////////////////////////////////
+
+#include "XConfig.h"
+#include "FontEngine.h"
+#include "kxftconfig.h"
+#include <ksavefile.h>
+#include <qtextstream.h>
+#include <fstream>
+#include <string.h>
+#include <qdir.h>
+#include <qregexp.h>
+#include <klocale.h>
+#include <sys/types.h>
+#include <signal.h>
+
+#if defined OS_Irix || defined OS_Solaris
+extern "C" unsigned int kfi_getPid(const char *proc, pid_t ppid);
+#else
+extern "C" unsigned int kfi_getPid(const char *proc, unsigned int ppid);
+#endif
+
+#define UNSCALED ":unscaled"
+
+namespace KFI
+{
+
+CXConfig::CXConfig(EType type, const QString &file)
+ : itsType(type),
+ itsFileName(file),
+ itsOk(false),
+ itsWritable(false)
+{
+ itsPaths.setAutoDelete(true);
+ readConfig();
+}
+
+bool CXConfig::configureDir(const QString &dir)
+{
+ //
+ // On systems without mkfontscale, the following will fail, so cant base
+ // return value upon that - hence only check return value of mkfontdir
+ Misc::doCmd("mkfontscale", QFile::encodeName(dir));
+ return Misc::doCmd("mkfontdir", QFile::encodeName(dir));
+}
+
+bool CXConfig::readConfig()
+{
+ itsOk=false;
+
+ switch(itsType)
+ {
+ case XFS:
+ itsOk=processXfs(true);
+ break;
+ case X11:
+ itsOk=processX11(true);
+ break;
+ }
+
+ if(itsOk)
+ itsWritable=Misc::fExists(itsFileName) ? Misc::fWritable(itsFileName)
+ : Misc::dWritable(Misc::getDir(itsFileName));
+ else
+ itsWritable=false;
+
+ return itsOk;
+}
+
+bool CXConfig::writeConfig()
+{
+ bool written=false;
+
+ //
+ // Check if file has been written since we last read it. If so, then re-read
+ // and add any new paths that we've added...
+ if(Misc::fExists(itsFileName) && Misc::getTimeStamp(itsFileName)!=itsTime)
+ {
+ CXConfig newConfig(itsType, itsFileName);
+
+ if(newConfig.ok())
+ {
+ TPath *path;
+
+ for(path=itsPaths.first(); path; path=itsPaths.next())
+ if(TPath::DIR==path->type && !path->orig)
+ newConfig.addPath(path->dir, path->unscaled);
+
+ written=newConfig.madeChanges() ? newConfig.writeConfig() : true;
+ }
+ }
+ else
+ switch(itsType)
+ {
+ case XFS:
+ written=processXfs(false);
+ break;
+ case X11:
+ written=processX11(false);
+ break;
+ }
+ if(written)
+ readConfig();
+
+ return written;
+}
+
+bool CXConfig::madeChanges()
+{
+ if(itsOk && itsWritable)
+ {
+ TPath *path;
+
+ for(path=itsPaths.first(); path; path=itsPaths.next())
+ if(!path->orig)
+ return true;
+ }
+
+ return false;
+}
+
+void CXConfig::addPath(const QString &dir, bool unscaled)
+{
+ if(itsWritable)
+ {
+ QString ds(Misc::dirSyntax(dir));
+
+ if(Misc::dExists(dir))
+ {
+ TPath *path=findPath(ds);
+
+ if(NULL==path)
+ itsPaths.append(new TPath(ds, unscaled, TPath::DIR, false));
+ }
+ }
+}
+
+bool CXConfig::inPath(TPath::EType type)
+{
+ if(itsOk && X11==itsType)
+ {
+ TPath *path=NULL;
+
+ for(path=itsPaths.first(); path; path=itsPaths.next())
+ if(type==path->type)
+ return true;
+ }
+
+ return false;
+}
+
+void CXConfig::refreshPaths(bool xfs)
+{
+ if(xfs)
+ {
+ if(Misc::root())
+ {
+ unsigned int xfsPid=kfi_getPid("xfs", 1);
+
+ if(xfsPid)
+ {
+ QString pid;
+
+ kill(xfsPid, SIGUSR1);
+ }
+ }
+ }
+ else
+ Misc::doCmd("xset", "fp", "rehash");
+}
+
+CXConfig::TPath * CXConfig::findPath(const QString &dir)
+{
+ TPath *path=NULL;
+ QString ds(Misc::dirSyntax(dir));
+
+ for(path=itsPaths.first(); path; path=itsPaths.next())
+ if(path->dir==ds)
+ return path;
+
+ return NULL;
+}
+
+static void processPath(char *str, QString &path, bool &unscaled)
+{
+ char *unsc=NULL;
+
+ unscaled=false;
+
+ if(NULL!=(unsc=strstr(str, UNSCALED)))
+ {
+ *unsc='\0';
+ unscaled=true;
+ }
+
+ path=str;
+
+ if(str[strlen(str)-1]!='/')
+ path+="/";
+}
+
+inline bool isWhitespace(char ch)
+{
+ return (' '==ch || '\t'==ch || '\n'==ch) ? true : false;
+}
+
+static unsigned int commentChars(char *buffer)
+{
+ unsigned int num=0;
+
+ if(buffer[0]=='#')
+ for(num=1; num<strlen(buffer)+1; ++num)
+ if(buffer[num]=='\n' || buffer[num]=='\0')
+ break;
+
+ return num;
+}
+
+static bool commentedOut(char *buffer, char *sect)
+{
+ if(sect!=buffer && '\n'!=*(sect-1))
+ {
+ char *ch;
+
+ for(ch=sect-1; ch>=buffer; ch--)
+ if(*ch=='\n')
+ break;
+ else if(*ch=='#')
+ return true;
+ }
+
+ return false;
+}
+
+static char * locateSection(char *buffer, const char *section)
+{
+ const char *sectionMarker ="Section";
+ const int sectionMarkerLen=7;
+
+ char *s=NULL,
+ *buf=buffer;
+
+ do
+ {
+ s=strstr(buf, sectionMarker);
+
+ if(s)
+ {
+ bool com=commentedOut(buffer, s);
+
+ buf=s+sectionMarkerLen;
+ if(com)
+ s=NULL;
+ else
+ {
+ // Skip any whitespace
+ for(s+=sectionMarkerLen; s && isWhitespace(*s); s++)
+ ;
+
+ // Now check section type
+ if(s && s==strstr(s, section)) // If found, then again skip past whitespace
+ for(s+=strlen(section); s && isWhitespace(*s); s++)
+ ;
+ else
+ s=NULL;
+ }
+ }
+ else
+ break;
+ }
+ while(!s);
+
+ return s;
+}
+
+static const char *endSectionMarker ="EndSection";
+static const int endSectionMarkerLen=10;
+
+static char *locateEndSection(char *buffer)
+{
+ char *s=NULL,
+ *buf=buffer;
+
+ do
+ {
+ s=strstr(buf, endSectionMarker);
+
+ if(s)
+ {
+ bool com=commentedOut(buffer, s);
+
+ buf=s+endSectionMarkerLen;
+ if(com)
+ s=NULL;
+ }
+ else
+ break;
+ }
+ while(!s);
+
+ return s;
+}
+
+static char * getItem(char **start, char **end, const char *key, unsigned int &size, bool remove, char *buffer)
+{
+ static const int constMaxItemLen = 1024;
+ static char item[constMaxItemLen+1];
+
+ unsigned int keyLen=strlen(key);
+
+ char *s=NULL,
+ *buf=*start;
+
+ do
+ {
+ s=strstr(buf, key);
+
+ if(s && s<*end)
+ {
+ bool com=commentedOut(buf, s);
+
+ buf=s+keyLen;
+ if(com)
+ s=NULL;
+ else
+ {
+ char *beg=s;
+ // Skip any whitespace
+ for(s+=keyLen; s && isWhitespace(*s); s++)
+ ;
+
+ if(s && *s=='\"' && s<*end)
+ {
+ char *e=strchr(s+1, '\"'),
+ *nl=strchr(s+1, '\n');
+
+ if(e && e<*end && (!nl || nl>e) && e-s<=constMaxItemLen)
+ {
+ memcpy(item, s+1, (e-s)-1);
+ item[(e-s)-1]='\0';
+
+ if(remove)
+ {
+ for(beg--; beg>=buffer && *beg!='\n' && *beg !='\"'; beg--)
+ ;
+ if(!nl)
+ nl=e+1;
+ memmove(beg, nl, ((buffer+size)-nl)+1);
+ size-=nl-beg;
+ *end-=nl-beg;
+ }
+ else
+ *start=e+1;
+
+ return item;
+ }
+ else
+ s=NULL;
+ }
+ else
+ s=NULL;
+ }
+ }
+ else
+ break;
+ }
+ while(!s);
+
+ return NULL;
+}
+
+bool CXConfig::processX11(bool read)
+{
+ std::ifstream x11(QFile::encodeName(itsFileName));
+ bool ok=false;
+
+ if(x11)
+ {
+ itsTime=Misc::getTimeStamp(itsFileName);
+
+ bool closed=false;
+
+ x11.seekg(0, std::ios::end);
+ unsigned int size=(std::streamoff) x11.tellg();
+
+ if(read)
+ itsPaths.clear();
+
+ if(size<65536) // Just incase...
+ {
+ char *buffer=new char [size+1];
+
+ if(buffer)
+ {
+ x11.seekg(0, std::ios::beg);
+ x11.read(buffer, size);
+
+ if(x11.good())
+ {
+ char *filesStart=NULL,
+ *filesEnd=NULL;
+
+ closed=true;
+ x11.close();
+ buffer[size]='\0';
+
+ if(NULL!=(filesStart=locateSection(buffer, "\"Files\"")) && NULL!=(filesEnd=locateEndSection(filesStart)))
+ {
+ char *pos=filesStart,
+ *item;
+
+ while(NULL!=(item=getItem(&pos, &filesEnd, "FontPath", size, !read, buffer)))
+ if(read) // Then save paths...
+ {
+ QString path;
+ bool unscaled;
+
+ processPath(item, path, unscaled);
+
+ if(NULL==findPath(path))
+ itsPaths.append(new TPath(path, unscaled, TPath::getType(path)));
+ }
+
+ if(read)
+ ok=true;
+ else
+ {
+ Misc::createBackup(itsFileName);
+
+ KSaveFile out(itsFileName);
+ FILE *fstream=out.fstream();
+
+ if(fstream)
+ {
+ char *from=buffer,
+ *modStart=NULL,
+ *modEnd=NULL;
+ bool foundFt=false;
+ TPath *path;
+
+ // Check if "freetype" OR "xtt" is loaded for usage of TTF's
+ if(NULL!=(modStart=locateSection(buffer, "\"Module\"")) && NULL!=(modEnd=locateEndSection(modStart)))
+ {
+ pos=modStart;
+
+ while(NULL!=(item=getItem(&pos, &modEnd, "Load", size, false, buffer)) && !foundFt)
+ if(0==strcmp(item, "freetype") || 0==strcmp(item, "xtt"))
+ foundFt=true;
+ }
+
+ if(!foundFt && modStart && modEnd && modStart<filesStart) // Then write mod section first...
+ {
+ fwrite(from, 1, modEnd-from, fstream);
+ if(!foundFt)
+ fputs(" Load \"freetype\"\n", fstream); // CPD TODO: Which is better xtt of freetype? Perhaps check locale?
+ fwrite(modEnd, 1, endSectionMarkerLen, fstream);
+ from=modEnd+endSectionMarkerLen;
+ }
+
+ fwrite(from, 1, filesEnd-from, fstream);
+
+ for(path=itsPaths.first(); path; path=itsPaths.next())
+ if(TPath::DIR!=path->type || Misc::dExists(path->dir))
+ {
+ QCString cPath(QFile::encodeName(Misc::xDirSyntax(path->dir)));
+
+ fputs(" FontPath \t\"", fstream);
+ fwrite(cPath.data(), 1, cPath.length(), fstream);
+ if(path->unscaled)
+ fputs(UNSCALED, fstream);
+ fputs("\"\n", fstream);
+ }
+
+ fwrite(filesEnd, 1, endSectionMarkerLen, fstream);
+ from=filesEnd+endSectionMarkerLen;
+
+ if(!foundFt && modStart && modEnd && modStart>filesStart) // Then write mod section last...
+ {
+ fwrite(from, 1, modEnd-from, fstream);
+ if(!foundFt)
+ fputs(" Load \"freetype\"\n", fstream);
+ fwrite(modEnd, 1, endSectionMarkerLen, fstream);
+ from=modEnd+endSectionMarkerLen;
+ }
+ if(((unsigned int)(from-buffer))<size)
+ fwrite(from, 1, size-(from-buffer), fstream);
+ ok=true;
+ }
+ }
+ }
+ }
+ delete [] buffer;
+ }
+ }
+ if(!closed)
+ x11.close();
+ }
+
+ return ok;
+}
+
+static bool isXfsKey(const char *str)
+{
+ static const char *constKeys[]=
+ {
+ "alternate-servers",
+ "cache-balance",
+ "cache-hi-mark",
+ "cache-low-mark",
+ "catalogue",
+ "client-limit",
+ "clone-self",
+ "default-point-size",
+ "default-resolutions",
+ "deferglyphs",
+ "error-file",
+ "no-listen",
+ "port",
+ "server-number",
+ "snf-format",
+ "trusted-clients",
+ "use-syslog",
+ NULL
+ };
+
+ for(unsigned int key=0; NULL!=constKeys[key]; ++key)
+ if(strstr(str, constKeys[key])==str)
+ {
+ unsigned int sLen=strlen(str),
+ kLen=strlen(constKeys[key]);
+
+ if(sLen>kLen && isWhitespace(str[kLen]) || '\0'==str[kLen] || '#'==str[kLen] || '='==str[kLen])
+ return true;
+ }
+
+ return false;
+}
+
+static char * getXfsPath(char *buffer, unsigned int &totalSize, unsigned int offsetSize)
+{
+ // Remove & return a path from the buffer
+ const unsigned int constMaxPathLen=8192;
+
+ static char path[constMaxPathLen];
+ bool found=false;
+
+ if(offsetSize<totalSize) // Just to make sure soething hasn't gone horribly wrong!
+ {
+ unsigned int i;
+
+ for(i=0; i<offsetSize && !found; i++)
+ if(!isWhitespace(buffer[i]) && ','!=buffer[i])
+ {
+ unsigned int comChars=commentChars(&buffer[i]);
+
+ if(comChars)
+ i+=comChars;
+ else
+ if(isXfsKey(&buffer[i]))
+ break;
+ else
+ {
+ // A path is terminated by either a comma, another key, or eof...
+
+ unsigned int j=0;
+
+ for(j=1; j<offsetSize-i && !found; j++)
+ if(buffer[i+j]==',' || buffer[i+j]=='\n' || buffer[i+j]=='\0' || isXfsKey(&buffer[i+j]))
+ {
+ if(j>0 && j<constMaxPathLen)
+ {
+ memcpy(path, &buffer[i], j);
+ path[j]='\0';
+ if(buffer[i+j]==',')
+ j++;
+ memmove(buffer, &buffer[i+j], (offsetSize-(i+j))+1);
+ totalSize-=(i+j);
+ found=true;
+ }
+ }
+ }
+ }
+ }
+
+ return found ? path : NULL;
+}
+
+bool CXConfig::processXfs(bool read)
+{
+ std::ifstream xfs(QFile::encodeName(itsFileName));
+ bool ok=false;
+
+ if(xfs)
+ {
+ itsTime=Misc::getTimeStamp(itsFileName);
+
+ bool closed=false;
+
+ xfs.seekg(0, std::ios::end);
+ unsigned int size= (std::streamoff) xfs.tellg();
+
+ if(read)
+ itsPaths.clear();
+
+ if(size<32768) // Just incase...
+ {
+ char *buffer=new char [size+1];
+
+ if(buffer)
+ {
+ xfs.seekg(0, std::ios::beg);
+ xfs.read(buffer, size);
+
+ if(xfs.good())
+ {
+ const char *constCatalogueStr="catalogue";
+ char *cat=NULL;
+ bool found=false,
+ formatError=false;
+
+ closed=true;
+ xfs.close();
+ buffer[size]='\0';
+
+ // Now remove the directory lists from the buffer...
+ do
+ if(NULL!=(cat=strstr(buffer, constCatalogueStr)))
+ {
+ cat+=strlen(constCatalogueStr);
+
+ if(!isWhitespace(*(cat-1)))
+ {
+ // Check it's not been commented out - by searching back until we get to the start of the buffer,
+ // a carriage-return, or a hash...
+
+ if(!commentedOut(buffer, cat))
+ {
+ // Look for '='
+ unsigned int i;
+
+ for(i=1; i<size-(cat-buffer) && !found && !formatError; ++i)
+ if(!isWhitespace(cat[i]))
+ {
+ unsigned int comChars=commentChars(&cat[i]);
+
+ if(comChars)
+ i+=comChars;
+ else
+ if(cat[i]!='=' || i+1>=size-(cat-buffer))
+ formatError=true;
+ else
+ {
+ char *path;
+
+ cat=&cat[i+1]; // skip equals sign
+ while(NULL!=(path=getXfsPath(cat, size, size-(cat-buffer))))
+ if(read)
+ {
+ QString str;
+ bool unscaled;
+ processPath(path, str, unscaled);
+
+ if(NULL==findPath(path))
+ itsPaths.append(new TPath(str, unscaled));
+ }
+
+ if(!read) // then must be write...
+ {
+ Misc::createBackup(itsFileName);
+
+ KSaveFile out(itsFileName);
+ FILE *fstream=out.fstream();
+
+ if(fstream)
+ {
+ bool first=true;
+ TPath *p=NULL;
+
+ fwrite(buffer, 1, cat-buffer, fstream);
+ fputc(' ', fstream);
+ for(p=itsPaths.first(); p; p=itsPaths.next())
+ if(Misc::dExists(p->dir))
+ {
+ QCString cPath(QFile::encodeName(Misc::xDirSyntax(p->dir)));
+
+ if(!first)
+ {
+ fputc(',', fstream);
+ fputc('\n', fstream);
+ }
+ fwrite(cPath.data(), 1, cPath.length(), fstream);
+ if(p->unscaled)
+ fputs(UNSCALED, fstream);
+ first=false;
+ }
+ fwrite(cat, 1, size-(cat-buffer), fstream);
+ ok=true;
+ }
+ }
+ else
+ ok=true;
+
+ found=true;
+ }
+ }
+ }
+ }
+ }
+ while(NULL!=cat && !found && !formatError);
+ }
+ delete [] buffer;
+ }
+ }
+ if(!closed)
+ xfs.close();
+ }
+
+ return ok;
+}
+
+
+CXConfig::TPath::EType CXConfig::TPath::getType(const QString &d)
+{
+ QString str(d);
+
+ str.replace(QRegExp("\\s*"), "");
+
+ return 0==str.find("unix/:")
+ ? FONT_SERVER
+ : "fontconfig"==str
+ ? FONT_CONFIG
+ : DIR;
+}
+
+}
diff --git a/kcontrol/kfontinst/kfontinst/XConfig.h b/kcontrol/kfontinst/kfontinst/XConfig.h
new file mode 100644
index 000000000..5a8ed1624
--- /dev/null
+++ b/kcontrol/kfontinst/kfontinst/XConfig.h
@@ -0,0 +1,114 @@
+#ifndef __X_CONFIG_H__
+#define __X_CONFIG_H__
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : KFI::CXConfig
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 05/05/2001
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2001, 2002, 2003, 2004
+///////////////////////////////////////////////////////////////////////////////
+
+#include "Misc.h"
+#include <qptrlist.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <time.h>
+
+namespace KFI
+{
+
+class CFontEngine;
+
+class CXConfig
+{
+ public:
+
+ struct TPath
+ {
+ enum EType
+ {
+ DIR,
+ FONT_SERVER,
+ FONT_CONFIG
+ };
+
+ TPath(const QString &d, bool u=false, EType t=DIR, bool o=true)
+ : dir(DIR==t ? Misc::dirSyntax(d) : d), unscaled(u), orig(o), type(t) {}
+
+ static EType getType(const QString &d);
+
+ QString dir;
+ bool unscaled,
+ orig; // Was dir in file when read?
+ EType type;
+ };
+
+ enum EType
+ {
+ XFS,
+ X11
+ };
+
+ public:
+
+ CXConfig(EType type, const QString &file);
+
+ static bool configureDir(const QString &dir);
+
+ bool ok() { return itsOk; }
+ bool writable() { return itsWritable; }
+ bool readConfig();
+ bool writeConfig();
+ bool madeChanges();
+ void addPath(const QString &dir, bool unscaled=false);
+ bool inPath(TPath::EType type);
+ bool xfsInPath() { return inPath(TPath::FONT_SERVER); }
+ bool fcInPath() { return inPath(TPath::FONT_CONFIG); }
+ void refreshPaths() { refreshPaths(XFS==itsType); }
+ void restart();
+ EType getType() { return itsType; }
+
+ static void refreshPaths(bool xfs);
+
+ private:
+
+ bool processX11(bool read);
+ bool processXfs(bool read);
+
+ TPath * findPath(const QString &dir);
+
+ private:
+
+ EType itsType;
+ QPtrList<TPath> itsPaths;
+ QString itsFileName,
+ itsInsertPos;
+ bool itsOk,
+ itsWritable;
+ time_t itsTime;
+};
+
+}
+
+#endif
diff --git a/kcontrol/kfontinst/kio/KioFonts.cpp b/kcontrol/kfontinst/kio/KioFonts.cpp
new file mode 100644
index 000000000..e5bc2d6af
--- /dev/null
+++ b/kcontrol/kfontinst/kio/KioFonts.cpp
@@ -0,0 +1,2534 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : KFI::CKioFonts
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 05/03/2003
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2003, 2004
+////////////////////////////////////////////////////////////////////////////////
+
+/***************************************************************************
+
+ NOTE: Large sections of this code are copied from kio_file
+ -- can't just inherit from kio_file as kio_file uses "error(...);
+ return;" So there is no way to know if an error occured!
+
+ ***************************************************************************/
+
+#include "KioFonts.h"
+#include <stdlib.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/types.h>
+#include <utime.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <kio/global.h>
+#include <kio/ioslave_defaults.h>
+#include <kio/netaccess.h>
+#include <kio/slaveinterface.h>
+#include <kio/connection.h>
+#include <qtextstream.h>
+#include <kmimetype.h>
+#include <kmessagebox.h>
+#include <kprocess.h>
+#include <qdir.h>
+#include <qdatastream.h>
+#include <qregexp.h>
+#include <kinstance.h>
+#include <klargefile.h>
+#include <ktempfile.h>
+#include <kdesu/su.h>
+#include <kprocess.h>
+#include <kdebug.h>
+#include <ktar.h>
+#include <kxftconfig.h>
+#include <fontconfig/fontconfig.h>
+#include "KfiConstants.h"
+#include "FcEngine.h"
+#include "Misc.h"
+#include <X11/Xlib.h>
+#include <fixx11h.h>
+#include <ctype.h>
+
+//#define KFI_FORCE_DEBUG_TO_STDERR
+
+#ifdef KFI_FORCE_DEBUG_TO_STDERR
+
+#include <qtextstream.h>
+QTextOStream ostr(stderr);
+#define KFI_DBUG ostr << "[" << (int)(getpid()) << "] "
+
+#else
+
+#define KFI_DBUG kdDebug() << "[" << (int)(getpid()) << "] "
+
+#endif
+
+#define MAX_IPC_SIZE (1024*32)
+#define TIMEOUT 2 // Time between last mod and writing files...
+#define MAX_NEW_FONTS 50 // #fonts that can be installed before automatically configuring (related to above)
+#define FC_CACHE_CMD "fc-cache"
+
+static const char * constMultipleExtension=".fonts.tar.gz"; // Fonts that have multiple files are returned as a .tar.gz!
+static const int constMaxLastDestTime=5;
+static const int constMaxFcCheckTime=10;
+
+extern "C"
+{
+ KDE_EXPORT int kdemain(int argc, char **argv);
+}
+
+int kdemain(int argc, char **argv)
+{
+ if (argc != 4)
+ {
+ fprintf(stderr, "Usage: kio_" KFI_KIO_FONTS_PROTOCOL " protocol domain-socket1 domain-socket2\n");
+ exit(-1);
+ }
+
+ KLocale::setMainCatalogue(KFI_CATALOGUE);
+
+ KInstance instance("kio_" KFI_KIO_FONTS_PROTOCOL);
+ KFI::CKioFonts slave(argv[2], argv[3]);
+
+ slave.dispatchLoop();
+
+ return 0;
+}
+
+namespace KFI
+{
+
+inline bool isSysFolder(const QString &sect)
+{
+ return i18n(KFI_KIO_FONTS_SYS)==sect || KFI_KIO_FONTS_SYS==sect;
+}
+
+inline bool isUserFolder(const QString &sect)
+{
+ return i18n(KFI_KIO_FONTS_USER)==sect || KFI_KIO_FONTS_USER==sect;
+}
+
+static QString removeMultipleExtension(const KURL &url)
+{
+ QString fname(url.fileName());
+ int pos;
+
+ if(-1!=(pos=fname.findRev(QString::fromLatin1(constMultipleExtension))))
+ fname=fname.left(pos);
+
+ return fname;
+}
+
+static QString modifyName(const QString &fname)
+{
+ static const char constSymbols[]={ '-', ' ', ':', 0 };
+
+ QString rv(fname);
+ int dotPos=rv.findRev('.');
+
+ if(-1!=dotPos)
+ {
+ unsigned int rvLen=rv.length();
+
+ for(unsigned int i=dotPos+1; i<rvLen; ++i)
+ rv[i]=rv[i].lower();
+ }
+
+ for(int s=0; constSymbols[s]; ++s)
+ rv=rv.replace(constSymbols[s], '_');
+
+ return rv;
+}
+
+static int getSize(const QCString &file)
+{
+ KDE_struct_stat buff;
+
+ if(-1!=KDE_lstat(file, &buff))
+ {
+ if (S_ISLNK(buff.st_mode))
+ {
+ char buffer2[1000];
+ int n=readlink(file, buffer2, 1000);
+ if(n!= -1)
+ buffer2[n]='\0';
+
+ if(-1==KDE_stat(file, &buff))
+ return -1;
+ }
+ return buff.st_size;
+ }
+
+ return -1;
+}
+
+static int getFontSize(const QString &file)
+{
+ int size=0;
+
+ KURL::List urls;
+ QStringList files;
+
+ Misc::getAssociatedUrls(KURL(file), urls);
+
+ files.append(file);
+
+ if(urls.count())
+ {
+ KURL::List::Iterator uIt,
+ uEnd=urls.end();
+
+ for(uIt=urls.begin(); uIt!=uEnd; ++uIt)
+ files.append((*uIt).path());
+ }
+
+ QStringList::Iterator it(files.begin()),
+ end(files.end());
+
+ for(; it!=end; ++it)
+ {
+ int s=getSize(QFile::encodeName(*it));
+
+ if(s>-1)
+ size+=s;
+ }
+
+ return size;
+}
+
+static int getSize(QValueList<FcPattern *> &patterns)
+{
+ QValueList<FcPattern *>::Iterator it,
+ end=patterns.end();
+ int size=0;
+
+ for(it=patterns.begin(); it!=end; ++it)
+ size+=getFontSize(CFcEngine::getFcString(*it, FC_FILE));
+
+ return size;
+}
+
+static void addAtom(KIO::UDSEntry &entry, unsigned int ID, long l, const QString &s=QString::null)
+{
+ KIO::UDSAtom atom;
+ atom.m_uds = ID;
+ atom.m_long = l;
+ atom.m_str = s;
+ entry.append(atom);
+}
+
+static bool createFolderUDSEntry(KIO::UDSEntry &entry, const QString &name, const QString &path, bool sys)
+{
+ KFI_DBUG << "createFolderUDSEntry " << name << ' ' << path << ' ' << sys << ' ' << endl;
+
+ KDE_struct_stat buff;
+ QCString cPath(QFile::encodeName(path));
+
+ entry.clear();
+
+ if(-1!=KDE_lstat(cPath, &buff))
+ {
+ addAtom(entry, KIO::UDS_NAME, 0, name);
+
+ if (S_ISLNK(buff.st_mode))
+ {
+ KFI_DBUG << path << " is a link" << endl;
+
+ char buffer2[1000];
+ int n=readlink(cPath, buffer2, 1000);
+ if(n!= -1)
+ buffer2[n]='\0';
+
+ addAtom(entry, KIO::UDS_LINK_DEST, 0, QString::fromLocal8Bit(buffer2));
+
+ if(-1==KDE_stat(cPath, &buff))
+ {
+ // It is a link pointing to nowhere
+ addAtom(entry, KIO::UDS_FILE_TYPE, S_IFMT - 1);
+ addAtom(entry, KIO::UDS_ACCESS, S_IRWXU | S_IRWXG | S_IRWXO);
+ addAtom(entry, KIO::UDS_SIZE, 0);
+ goto notype;
+ }
+ }
+
+ addAtom(entry, KIO::UDS_FILE_TYPE, buff.st_mode&S_IFMT);
+ addAtom(entry, KIO::UDS_ACCESS, buff.st_mode&07777);
+ addAtom(entry, KIO::UDS_SIZE, buff.st_size);
+
+ notype:
+ addAtom(entry, KIO::UDS_MODIFICATION_TIME, buff.st_mtime);
+
+ struct passwd *user = getpwuid(buff.st_uid);
+ addAtom(entry, KIO::UDS_USER, 0, user ? user->pw_name : QString::number(buff.st_uid).latin1());
+
+ struct group *grp = getgrgid(buff.st_gid);
+ addAtom(entry, KIO::UDS_GROUP, 0, grp ? grp->gr_name : QString::number(buff.st_gid).latin1());
+
+ addAtom(entry, KIO::UDS_ACCESS_TIME, buff.st_atime);
+ addAtom(entry, KIO::UDS_MIME_TYPE, 0, sys
+ ? KFI_KIO_FONTS_PROTOCOL"/system-folder"
+ : KFI_KIO_FONTS_PROTOCOL"/folder");
+ addAtom(entry, KIO::UDS_GUESSED_MIME_TYPE, 0, "application/octet-stream");
+ QString url(KFI_KIO_FONTS_PROTOCOL+QString::fromLatin1(":/"));
+ return true;
+ }
+ else if (sys && !Misc::root()) // Default system fonts folder does not actually exist yet!
+ {
+ KFI_DBUG << "Default system folder (" << path << ") does not yet exist, so create dummy entry" << endl;
+ addAtom(entry, KIO::UDS_NAME, 0, name);
+ addAtom(entry, KIO::UDS_FILE_TYPE, S_IFDIR);
+ addAtom(entry, KIO::UDS_ACCESS, 0744);
+ addAtom(entry, KIO::UDS_USER, 0, "root");
+ addAtom(entry, KIO::UDS_GROUP, 0, "root");
+ addAtom(entry, KIO::UDS_MIME_TYPE, 0, KFI_KIO_FONTS_PROTOCOL"/system-folder");
+ addAtom(entry, KIO::UDS_GUESSED_MIME_TYPE, 0, "application/octet-stream");
+
+ return true;
+ }
+
+
+ return false;
+}
+
+static bool createFontUDSEntry(KIO::UDSEntry &entry, const QString &name, QValueList<FcPattern *> &patterns, bool sys)
+{
+ KFI_DBUG << "createFontUDSEntry " << name << ' ' << patterns.count() << endl;
+
+ bool multiple=true;
+
+ if(1==patterns.count()) // Only one font file, but are there any .pfm or .afm files?
+ {
+ KURL::List urls;
+
+ Misc::getAssociatedUrls(KURL(CFcEngine::getFcString(patterns.first(), FC_FILE)), urls);
+
+ if(0==urls.count())
+ multiple=false;
+ }
+
+ //
+ // In case of mixed bitmap/scalable - prefer scalable
+ QValueList<FcPattern *> sortedPatterns;
+ QValueList<FcPattern *>::Iterator it,
+ end(patterns.end());
+ FcBool b=FcFalse;
+
+ for(it=patterns.begin(); it!=end; ++it)
+ if(FcResultMatch==FcPatternGetBool(*it, FC_SCALABLE, 0, &b) && b)
+ sortedPatterns.prepend(*it);
+ else
+ sortedPatterns.append(*it);
+
+ end=sortedPatterns.end();
+ entry.clear();
+ addAtom(entry, KIO::UDS_SIZE, getSize(patterns));
+
+ for(it=sortedPatterns.begin(); it!=end; ++it)
+ {
+ QString path(CFcEngine::getFcString(*it, FC_FILE));
+ QCString cPath(QFile::encodeName(path));
+ KDE_struct_stat buff;
+
+ if(-1!=KDE_lstat(cPath, &buff))
+ {
+ addAtom(entry, KIO::UDS_NAME, 0, name);
+
+ if (S_ISLNK(buff.st_mode))
+ {
+ KFI_DBUG << path << " is a link" << endl;
+
+ char buffer2[1000];
+ int n=readlink(cPath, buffer2, 1000);
+
+ if(n!= -1)
+ buffer2[n]='\0';
+
+ addAtom(entry, KIO::UDS_LINK_DEST, 0, QString::fromLocal8Bit(buffer2));
+
+ if(-1==KDE_stat(cPath, &buff))
+ {
+ // It is a link pointing to nowhere
+ addAtom(entry, KIO::UDS_FILE_TYPE, S_IFMT - 1);
+ addAtom(entry, KIO::UDS_ACCESS, S_IRWXU | S_IRWXG | S_IRWXO);
+ goto notype;
+ }
+ }
+
+ addAtom(entry, KIO::UDS_FILE_TYPE, buff.st_mode&S_IFMT);
+ addAtom(entry, KIO::UDS_ACCESS, buff.st_mode&07777);
+
+ notype:
+ addAtom(entry, KIO::UDS_MODIFICATION_TIME, buff.st_mtime);
+
+ struct passwd *user = getpwuid(buff.st_uid);
+ addAtom(entry, KIO::UDS_USER, 0, user ? user->pw_name : QString::number(buff.st_uid).latin1());
+
+ struct group *grp = getgrgid(buff.st_gid);
+ addAtom(entry, KIO::UDS_GROUP, 0, grp ? grp->gr_name : QString::number(buff.st_gid).latin1());
+
+ addAtom(entry, KIO::UDS_ACCESS_TIME, buff.st_atime);
+ addAtom(entry, KIO::UDS_MIME_TYPE, 0, KMimeType::findByPath(path, 0, true)->name());
+ addAtom(entry, KIO::UDS_GUESSED_MIME_TYPE, 0, "application/octet-stream");
+
+ QString url(KFI_KIO_FONTS_PROTOCOL+QString::fromLatin1(":/"));
+
+ if(!Misc::root())
+ {
+ url+=sys ? i18n(KFI_KIO_FONTS_SYS) : i18n(KFI_KIO_FONTS_USER);
+ url+=QString::fromLatin1("/");
+ }
+ if(multiple)
+ url+=name+QString::fromLatin1(constMultipleExtension);
+ else
+ url+=Misc::getFile(path);
+ addAtom(entry, KIO::UDS_URL, 0, url);
+ return true; // This file was OK, so use its values...
+ }
+ }
+ return false;
+}
+
+enum EUrlStatus
+{
+ BAD_URL,
+ URL_OK,
+ REDIRECT_URL
+};
+
+static KURL getRedirect(const KURL &u)
+{
+ // Go from fonts:/System to fonts:/
+
+ KURL redirect(u);
+ QString path(u.path()),
+ sect(CKioFonts::getSect(path));
+
+ path.remove(sect);
+ path.replace("//", "/");
+ redirect.setPath(path);
+
+ KFI_DBUG << "Redirect from " << u.path() << " to " << redirect.path() << endl;
+ return redirect;
+}
+
+static bool nonRootSys(const KURL &u)
+{
+ return !Misc::root() && isSysFolder(CKioFonts::getSect(u.path()));
+}
+
+static QString getFontFolder(const QString &defaultDir, const QString &root, QStringList &dirs)
+{
+ if(dirs.contains(defaultDir))
+ return defaultDir;
+ else
+ {
+ QStringList::Iterator it,
+ end=dirs.end();
+ bool found=false;
+
+ for(it=dirs.begin(); it!=end && !found; ++it)
+ if(0==(*it).find(root))
+ return *it;
+ }
+
+ return QString::null;
+}
+
+static bool writeAll(int fd, const char *buf, size_t len)
+{
+ while(len>0)
+ {
+ ssize_t written=write(fd, buf, len);
+ if (written<0 && EINTR!=errno)
+ return false;
+ buf+=written;
+ len-=written;
+ }
+ return true;
+}
+
+static bool checkExt(const char *fname, const char *ext)
+{
+ unsigned int len=strlen(fname);
+
+ return len>4 ? (fname[len-4]=='.' && tolower(fname[len-3])==ext[0] && tolower(fname[len-2])==ext[1] &&
+ tolower(fname[len-1])==ext[2])
+ : false;
+}
+
+static bool isAAfm(const QString &fname)
+{
+ if(checkExt(QFile::encodeName(fname), "afm")) // CPD? Is this a necessary check?
+ {
+ QFile file(fname);
+
+ if(file.open(IO_ReadOnly))
+ {
+ QTextStream stream(&file);
+ QString line;
+
+ for(int lc=0; lc<30 && !stream.atEnd(); ++lc)
+ {
+ line=stream.readLine();
+
+ if(line.contains("StartFontMetrics"))
+ {
+ file.close();
+ return true;
+ }
+ }
+
+ file.close();
+ }
+ }
+
+ return false;
+}
+
+static bool isAPfm(const QString &fname)
+{
+ bool ok=false;
+
+ // I know extension checking is bad, but Ghostscript's pf2afm requires the pfm file to
+ // have the .pfm extension...
+ if(checkExt(QFile::encodeName(fname), "pfm"))
+ {
+ //
+ // OK, the extension matches, so perform a little contents checking...
+ FILE *f=fopen(QFile::encodeName(fname).data(), "r");
+
+ if(f)
+ {
+ static const unsigned long constCopyrightLen = 60;
+ static const unsigned long constTypeToExt = 49;
+ static const unsigned long constExtToFname = 20;
+ static const unsigned long constExtLen = 30;
+ static const unsigned long constFontnameMin = 75;
+ static const unsigned long constFontnameMax = 512;
+
+ unsigned short version=0,
+ type=0,
+ extlen=0;
+ unsigned long length=0,
+ fontname=0,
+ fLength=0;
+
+ fseek(f, 0, SEEK_END);
+ fLength=ftell(f);
+ fseek(f, 0, SEEK_SET);
+
+ if(2==fread(&version, 1, 2, f) && // Read version
+ 4==fread(&length, 1, 4, f) && // length...
+ length==fLength &&
+ 0==fseek(f, constCopyrightLen, SEEK_CUR) && // Skip copyright notice...
+ 2==fread(&type, 1, 2, f) &&
+ 0==fseek(f, constTypeToExt, SEEK_CUR) &&
+ 2==fread(&extlen, 1, 2, f) &&
+ extlen==constExtLen &&
+ 0==fseek(f, constExtToFname, SEEK_CUR) &&
+ 4==fread(&fontname, 1, 4, f) &&
+ fontname>constFontnameMin && fontname<constFontnameMax)
+ ok=true;
+ fclose(f);
+ }
+ }
+
+ return ok;
+}
+
+//
+// This function is *only* used for the generation of AFMs from PFMs.
+static bool isAType1(const QString &fname)
+{
+ static const char * constStr="%!PS-AdobeFont-";
+ static const unsigned int constStrLen=15;
+ static const unsigned int constPfbOffset=6;
+ static const unsigned int constPfbLen=constStrLen+constPfbOffset;
+
+ QCString name(QFile::encodeName(fname));
+ char buffer[constPfbLen];
+ bool match=false;
+
+ if(checkExt(name, "pfa"))
+ {
+ FILE *f=fopen(name.data(), "r");
+
+ if(f)
+ {
+ if(constStrLen==fread(buffer, 1, constStrLen, f))
+ match=0==memcmp(buffer, constStr, constStrLen);
+ fclose(f);
+ }
+ }
+ else if(checkExt(name, "pfb"))
+ {
+ static const char constPfbMarker=0x80;
+
+ FILE *f=fopen(name.data(), "r");
+
+ if(f)
+ {
+ if(constPfbLen==fread(buffer, 1, constPfbLen, f))
+ match=buffer[0]==constPfbMarker && 0==memcmp(&buffer[constPfbOffset], constStr, constStrLen);
+ fclose(f);
+ }
+ }
+
+ return match;
+}
+
+static QString getMatch(const QString &file, const char *extension)
+{
+ QString f(Misc::changeExt(file, extension));
+
+ return Misc::fExists(f) ? f : QString::null;
+}
+
+inline bool isHidden(const KURL &u)
+{
+ return QChar('.')==u.fileName()[0];
+}
+
+struct FontList
+{
+ struct Path
+ {
+ Path(const QString &p=QString::null) : orig(p) { }
+
+ QString orig,
+ modified;
+
+ bool operator==(const Path &p) const { return p.orig==orig; }
+ };
+
+ FontList(const QString &n=QString::null, const QString &p=QString::null) : name(n) { if(!p.isEmpty()) paths.append(Path(p)); }
+
+ QString name;
+ QValueList<Path> paths;
+
+ bool operator==(const FontList &f) const { return f.name==name; }
+};
+
+//
+// This function returns a set of maping of from -> to for copy/move operations
+static bool getFontList(const QStringList &files, QMap<QString, QString> &map)
+{
+ //
+ // First of all create a list of font files, and their paths
+ QStringList::ConstIterator it=files.begin(),
+ end=files.end();
+ QValueList<FontList> list;
+
+ for(;it!=end; ++it)
+ {
+ QString name(Misc::getFile(*it)),
+ path(Misc::getDir(*it));
+ QValueList<FontList>::Iterator entry=list.find(FontList(name));
+
+ if(entry!=list.end())
+ {
+ if(!(*entry).paths.contains(path))
+ (*entry).paths.append(path);
+ }
+ else
+ list.append(FontList(name, path));
+ }
+
+ QValueList<FontList>::Iterator fIt(list.begin()),
+ fEnd(list.end());
+
+ for(; fIt!=fEnd; ++fIt)
+ {
+ QValueList<FontList::Path>::Iterator pBegin((*fIt).paths.begin()),
+ pIt(++pBegin),
+ pEnd((*fIt).paths.end());
+ --pBegin;
+
+ if((*fIt).paths.count()>1)
+ {
+ // There's more than 1 file with the same name, but in a different locations
+ // therefore, take the unique part of the path, and replace / with _
+ // e.g.
+ // /usr/X11R6/lib/X11/fonts/75dpi/times.pcf.gz
+ // /usr/X11R6/lib/X11/fonts/100dpi/times.pcf.gz
+ //
+ // Will produce:
+ // 75dpi_times.pcf.gz
+ // 100dpi_times.pcf.gz
+ unsigned int beginLen((*pBegin).orig.length());
+
+ for(; pIt!=pEnd; ++pIt)
+ {
+ unsigned int len=QMIN((*pIt).orig.length(), beginLen);
+
+ for(unsigned int i=0; i<len; ++i)
+ if((*pIt).orig[i]!=(*pBegin).orig[i])
+ {
+ (*pIt).modified=(*pIt).orig.mid(i);
+ (*pIt).modified=(*pIt).modified.replace('/', '_');
+ if((*pBegin).modified.isEmpty())
+ {
+ (*pBegin).modified=(*pBegin).orig.mid(i);
+ (*pBegin).modified=(*pBegin).modified.replace('/', '_');
+ }
+ break;
+ }
+ }
+ }
+ for(pIt=(*fIt).paths.begin(); pIt!=pEnd; ++pIt)
+ map[(*pIt).orig+(*fIt).name]=(*pIt).modified+(*fIt).name;
+ }
+
+ return list.count() ? true : false;
+}
+
+CKioFonts::CKioFonts(const QCString &pool, const QCString &app)
+ : KIO::SlaveBase(KFI_KIO_FONTS_PROTOCOL, pool, app),
+ itsRoot(Misc::root()),
+ itsUsingFcFpe(false),
+ itsUsingXfsFpe(false),
+ itsHasSys(false),
+ itsAddToSysFc(false),
+ itsFontChanges(0),
+ itsLastDest(DEST_UNCHANGED),
+ itsLastDestTime(0),
+ itsLastFcCheckTime(0),
+ itsFontList(NULL)
+{
+ KFI_DBUG << "Constructor" << endl;
+
+ // Set core dump size to 0 because we will have
+ // root's password in memory.
+ struct rlimit rlim;
+ rlim.rlim_cur=rlim.rlim_max=0;
+ itsCanStorePasswd=setrlimit(RLIMIT_CORE, &rlim) ? false : true;
+
+ //
+ // Check with fontconfig for folder locations...
+ //
+ // 1. Get list of fontconfig dirs
+ // 2. For user, look for any starting with $HOME - but prefer $HOME/.fonts
+ // 3. For system, look for any starting with /usr/local/share - but prefer /usr/local/share/fonts
+ // 4. If either are not found, then add to local.conf / .fonts.conf
+
+ FcStrList *list=FcConfigGetFontDirs(FcInitLoadConfigAndFonts());
+ QStringList dirs;
+ FcChar8 *dir;
+
+ while((dir=FcStrListNext(list)))
+ dirs.append(Misc::dirSyntax((const char *)dir));
+
+ EFolder mainFolder=FOLDER_SYS;
+
+ if(!itsRoot)
+ {
+ QString home(Misc::dirSyntax(QDir::homeDirPath())),
+ defaultDir(Misc::dirSyntax(QDir::homeDirPath()+"/.fonts/")),
+ dir(getFontFolder(defaultDir, home, dirs));
+
+ if(dir.isEmpty()) // Then no $HOME/ was found in fontconfigs dirs!
+ {
+ KXftConfig xft(KXftConfig::Dirs, false);
+ xft.addDir(defaultDir);
+ xft.apply();
+ dir=defaultDir;
+ }
+ mainFolder=FOLDER_USER;
+ itsFolders[FOLDER_USER].location=dir;
+ }
+
+ QString sysDefault("/usr/local/share/fonts/"),
+ sysDir(getFontFolder(sysDefault, "/usr/local/share/", dirs));
+
+ if(sysDir.isEmpty())
+ {
+ if(itsRoot)
+ {
+ KXftConfig xft(KXftConfig::Dirs, true);
+ xft.addDir(sysDefault);
+ xft.apply();
+ }
+ else
+ itsAddToSysFc=true;
+
+ sysDir=sysDefault;
+ }
+
+ itsFolders[FOLDER_SYS].location=sysDir;
+
+ //
+ // Ensure exists
+ if(!Misc::dExists(itsFolders[mainFolder].location))
+ Misc::createDir(itsFolders[mainFolder].location);
+
+ //
+ // Work out best params to send to kfontinst
+
+ // ...determine if X already knows about the system font path...
+ Display *xDisplay=XOpenDisplay(NULL);
+
+ if(xDisplay)
+ {
+ int numPaths=0;
+ char **paths=XGetFontPath(xDisplay, &numPaths);
+
+ if(numPaths>0)
+ for(int path=0; path<numPaths && !itsUsingFcFpe; ++path)
+ if(paths[path][0]=='/')
+ {
+ if(Misc::dirSyntax(paths[path])==itsFolders[FOLDER_SYS].location)
+ itsHasSys=true;
+ }
+ else
+ {
+ QString str(paths[path]);
+
+ str.replace(QRegExp("\\s*"), "");
+
+ if(0==str.find("unix/:"))
+ itsUsingXfsFpe=true;
+ else if("fontconfig"==str)
+ itsUsingFcFpe=true;
+ }
+ XFreeFontPath(paths);
+ XCloseDisplay(xDisplay);
+ }
+}
+
+CKioFonts::~CKioFonts()
+{
+ KFI_DBUG << "Destructor" << endl;
+ doModified();
+}
+
+void CKioFonts::listDir(const KURL &url)
+{
+ KFI_DBUG << "listDir " << url.path() << endl;
+
+ if(updateFontList() && checkUrl(url, true))
+ {
+ KIO::UDSEntry entry;
+ int size=0;
+
+ if(itsRoot || QStringList::split('/', url.path(), false).count()!=0)
+ {
+ EFolder folder=getFolder(url);
+
+ totalSize(itsFolders[folder].fontMap.count());
+ if(itsFolders[folder].fontMap.count())
+ {
+ QMap<QString, QValueList<FcPattern *> >::Iterator it=itsFolders[folder].fontMap.begin(),
+ end=itsFolders[folder].fontMap.end();
+
+ for ( ; it != end; ++it)
+ {
+ entry.clear();
+ if(createFontUDSEntry(entry, it.key(), it.data(), FOLDER_SYS==folder))
+ listEntry(entry, false);
+ }
+ }
+ }
+ else
+ {
+ size=2;
+ totalSize(size);
+ createFolderUDSEntry(entry, i18n(KFI_KIO_FONTS_USER), itsFolders[FOLDER_USER].location, false);
+ listEntry(entry, false);
+ createFolderUDSEntry(entry, i18n(KFI_KIO_FONTS_SYS), itsFolders[FOLDER_SYS].location, true);
+ listEntry(entry, false);
+ }
+
+ listEntry(size ? entry : KIO::UDSEntry(), true);
+ finished();
+ }
+
+ KFI_DBUG << "listDir - finished!" << endl;
+}
+
+void CKioFonts::stat(const KURL &url)
+{
+ KFI_DBUG << "stat " << url.prettyURL() << endl;
+
+ if(updateFontList() && checkUrl(url, true))
+ {
+ QString path(url.path(-1));
+
+ if(path.isEmpty())
+ {
+ error(KIO::ERR_COULD_NOT_STAT, url.prettyURL());
+ return;
+ }
+
+ QStringList pathList(QStringList::split('/', path, false));
+ KIO::UDSEntry entry;
+ bool err=false;
+
+ switch(pathList.count())
+ {
+ case 0:
+ err=!createFolderUDSEntry(entry, i18n("Fonts"), itsFolders[itsRoot ? FOLDER_SYS : FOLDER_USER].location, false);
+ break;
+ case 1:
+ if(itsRoot)
+ err=!createStatEntry(entry, url, FOLDER_SYS);
+ else
+ if(isUserFolder(pathList[0]))
+ err=!createFolderUDSEntry(entry, i18n(KFI_KIO_FONTS_USER), itsFolders[FOLDER_USER].location, false);
+ else if(isSysFolder(pathList[0]))
+ err=!createFolderUDSEntry(entry, i18n(KFI_KIO_FONTS_SYS), itsFolders[FOLDER_USER].location, true);
+ else
+ {
+ error(KIO::ERR_SLAVE_DEFINED,
+ i18n("Please specify \"%1\" or \"%2\".").arg(i18n(KFI_KIO_FONTS_USER)).arg(i18n(KFI_KIO_FONTS_SYS)));
+ return;
+ }
+ break;
+ default:
+ err=!createStatEntry(entry, url, getFolder(url));
+ }
+
+ if(err)
+ {
+ error(KIO::ERR_DOES_NOT_EXIST, url.prettyURL());
+ return;
+ }
+
+ statEntry(entry);
+ finished();
+ }
+}
+
+bool CKioFonts::createStatEntry(KIO::UDSEntry &entry, const KURL &url, EFolder folder)
+{
+ KFI_DBUG << "createStatEntry " << url.path() << endl;
+
+ QMap<QString, QValueList<FcPattern *> >::Iterator it=getMap(url);
+
+ if(it!=itsFolders[folder].fontMap.end())
+ return createFontUDSEntry(entry, it.key(), it.data(), FOLDER_SYS==folder);
+ return false;
+}
+
+void CKioFonts::get(const KURL &url)
+{
+ KFI_DBUG << "get " << url.path() << " query:" << url.query() << endl;
+
+ bool thumb="1"==metaData("thumbnail");
+ QStringList srcFiles;
+
+ if(updateFontList() && checkUrl(url) && getSourceFiles(url, srcFiles)) // Any error will be logged in getSourceFiles
+ {
+ //
+ // The thumbnail job always donwloads non-local files to /tmp/... and passes this file name to the thumbnail
+ // creator. However, in the case of fonts which are split among many files, this wont work. Therefore, when the
+ // thumbnail code asks for the font to donwload, just return the URL used. This way the font-thumbnail creator can
+ // read this and just ask Xft/fontconfig for the font data.
+ if(thumb)
+ {
+ QByteArray array;
+ QTextOStream stream(array);
+
+ emit mimeType("text/plain");
+
+ KFI_DBUG << "hasMetaData(\"thumbnail\"), so return: " << url.prettyURL() << endl;
+
+ stream << url.prettyURL();
+ totalSize(array.size());
+ data(array);
+ processedSize(array.size());
+ data(QByteArray());
+ processedSize(array.size());
+ finished();
+ return;
+ }
+
+ QString realPath,
+ useMime;
+ KDE_struct_stat buff;
+ bool multiple=false;
+
+ if(1==srcFiles.count())
+ realPath=srcFiles.first();
+ else // Font is made up of multiple files - so create .tar.gz of them all!
+ {
+ KTempFile tmpFile;
+ KTar tar(tmpFile.name(), "application/x-gzip");
+
+ tmpFile.setAutoDelete(false);
+ realPath=tmpFile.name();
+
+ if(tar.open(IO_WriteOnly))
+ {
+ QMap<QString, QString> map;
+
+ getFontList(srcFiles, map);
+
+ QMap<QString, QString>::Iterator fIt(map.begin()),
+ fEnd(map.end());
+
+ //
+ // Iterate through created list, and add to tar archive
+ for(; fIt!=fEnd; ++fIt)
+ tar.addLocalFile(fIt.key(), fIt.data());
+
+ multiple=true;
+ tar.close();
+ }
+ }
+
+ QCString realPathC(QFile::encodeName(realPath));
+ KFI_DBUG << "real: " << realPathC << endl;
+
+ if (-2==KDE_stat(realPathC.data(), &buff))
+ error(EACCES==errno ? KIO::ERR_ACCESS_DENIED : KIO::ERR_DOES_NOT_EXIST, url.prettyURL());
+ else if (S_ISDIR(buff.st_mode))
+ error(KIO::ERR_IS_DIRECTORY, url.prettyURL());
+ else if (!S_ISREG(buff.st_mode))
+ error(KIO::ERR_CANNOT_OPEN_FOR_READING, url.prettyURL());
+ else
+ {
+ int fd = KDE_open(realPathC.data(), O_RDONLY);
+
+ if (fd < 0)
+ error(KIO::ERR_CANNOT_OPEN_FOR_READING, url.prettyURL());
+ else
+ {
+ // Determine the mimetype of the file to be retrieved, and emit it.
+ // This is mandatory in all slaves (for KRun/BrowserRun to work).
+ emit mimeType(useMime.isEmpty() ? KMimeType::findByPath(realPathC, buff.st_mode, true)->name() : useMime);
+
+ totalSize(buff.st_size);
+
+ KIO::filesize_t processed=0;
+ char buffer[MAX_IPC_SIZE];
+ QByteArray array;
+
+ while(1)
+ {
+ int n=::read(fd, buffer, MAX_IPC_SIZE);
+ if (-1==n)
+ {
+ if (errno == EINTR)
+ continue;
+ error(KIO::ERR_COULD_NOT_READ, url.prettyURL());
+ close(fd);
+ if(multiple)
+ ::unlink(realPathC);
+ return;
+ }
+ if (0==n)
+ break; // Finished
+
+ array.setRawData(buffer, n);
+ data(array);
+ array.resetRawData(buffer, n);
+
+ processed+=n;
+ processedSize(processed);
+ }
+
+ data(QByteArray());
+ close(fd);
+
+ processedSize(buff.st_size);
+ finished();
+ }
+ }
+ if(multiple)
+ ::unlink(realPathC);
+ }
+}
+
+void CKioFonts::put(const KURL &u, int mode, bool overwrite, bool resume)
+{
+ KFI_DBUG << "put " << u.path() << endl;
+
+ if(isHidden(u))
+ {
+ error(KIO::ERR_WRITE_ACCESS_DENIED, u.prettyURL());
+ return;
+ }
+
+ // updateFontList(); // CPD: dont update font list upon a put - is too slow. Just stat on filename!
+
+ //checkUrl(u) // CPD: Don't need to check URL, as the call to "confirmUrl()" below will sort out any probs!
+
+ KURL url(u);
+ bool changed=confirmUrl(url),
+ nrs=nonRootSys(url);
+ EFolder destFolder(getFolder(url));
+ QString dest=itsFolders[destFolder].location+modifyName(url.fileName()),
+ passwd;
+ QCString destC=QFile::encodeName(dest);
+ KDE_struct_stat buffDest;
+ bool destExists=(KDE_lstat(destC.data(), &buffDest)!= -1);
+
+ if (destExists && !overwrite && !resume)
+ {
+ error(KIO::ERR_FILE_ALREADY_EXIST, url.prettyURL());
+ return;
+ }
+
+ if(nrs) // Need to check can get root passwd before start download...
+ {
+ passwd=getRootPasswd();
+
+ if(passwd.isEmpty())
+ {
+ error(KIO::ERR_SLAVE_DEFINED, i18n("Could not access \"%1\" folder.").arg(i18n(KFI_KIO_FONTS_SYS)));
+ return;
+ }
+ }
+
+ //
+ // As we don't get passed a mime-type the following needs to happen:
+ //
+ // 1. Download to a temporary file
+ // 2. Check with FreeType that the file is a font, or that it is
+ // an AFM or PFM file
+ // 3. If its OK, then get the fonts "name" from
+ KTempFile tmpFile;
+ QCString tmpFileC(QFile::encodeName(tmpFile.name()));
+
+ tmpFile.setAutoDelete(true);
+
+ if(putReal(tmpFile.name(), tmpFileC, destExists, mode, resume))
+ {
+ if(!checkFile(tmpFile.name())) // error logged in checkFile
+ return;
+
+ if(nrs) // Ask root to copy the font...
+ {
+ QCString cmd;
+
+ if(!Misc::dExists(itsFolders[destFolder].location))
+ {
+ cmd+="mkdir ";
+ cmd+=QFile::encodeName(KProcess::quote(itsFolders[destFolder].location));
+ cmd+=" && chmod 0755 ";
+ cmd+=QFile::encodeName(KProcess::quote(itsFolders[destFolder].location));
+ cmd+=" && ";
+ }
+ cmd+="cp -f ";
+ cmd+=QFile::encodeName(KProcess::quote(tmpFileC));
+ cmd+=" ";
+ cmd+=QFile::encodeName(KProcess::quote(destC));
+ cmd+=" && chmod 0644 ";
+ cmd+=destC;
+
+ if(!itsCanStorePasswd)
+ createRootRefreshCmd(cmd);
+
+ // Get root to move this to fonts folder...
+ if(doRootCmd(cmd, passwd))
+ {
+ modified(FOLDER_SYS);
+ createAfm(dest, true, passwd);
+ }
+ else
+ {
+ error(KIO::ERR_SLAVE_DEFINED, i18n("Could not access \"%1\" folder.").arg(i18n(KFI_KIO_FONTS_SYS)));
+ return;
+ }
+ }
+ else // Move it to our font folder...
+ {
+ tmpFile.setAutoDelete(false);
+ if(Misc::doCmd("mv", "-f", tmpFileC, destC))
+ {
+ ::chmod(destC.data(), Misc::FILE_PERMS);
+ modified(FOLDER_USER);
+ createAfm(dest);
+ }
+ else
+ {
+ error(KIO::ERR_SLAVE_DEFINED, i18n("Could not access \"%1\" folder.").arg(i18n(KFI_KIO_FONTS_USER)));
+ return;
+ }
+ }
+
+ finished();
+
+ if(changed)
+ itsLastDestTime=time(NULL);
+ }
+}
+
+bool CKioFonts::putReal(const QString &destOrig, const QCString &destOrigC, bool origExists,
+ int mode, bool resume)
+{
+ bool markPartial=config()->readBoolEntry("MarkPartial", true);
+ QString dest;
+
+ if (markPartial)
+ {
+ QString destPart(destOrig+QString::fromLatin1(".part"));
+ QCString destPartC(QFile::encodeName(destPart));
+
+ dest = destPart;
+
+ KDE_struct_stat buffPart;
+ bool partExists=(-1!=KDE_stat(destPartC.data(), &buffPart));
+
+ if (partExists && !resume && buffPart.st_size>0)
+ {
+ // Maybe we can use this partial file for resuming
+ // Tell about the size we have, and the app will tell us
+ // if it's ok to resume or not.
+ resume=canResume(buffPart.st_size);
+
+ if (!resume)
+ if (!::remove(destPartC.data()))
+ partExists = false;
+ else
+ {
+ error(KIO::ERR_CANNOT_DELETE_PARTIAL, destPart);
+ return false;
+ }
+ }
+ }
+ else
+ {
+ dest = destOrig;
+ if (origExists && !resume)
+ ::remove(destOrigC.data());
+ // Catch errors when we try to open the file.
+ }
+
+ QCString destC(QFile::encodeName(dest));
+
+ int fd;
+
+ if (resume)
+ {
+ fd = KDE_open(destC.data(), O_RDWR); // append if resuming
+ KDE_lseek(fd, 0, SEEK_END); // Seek to end
+ }
+ else
+ {
+ // WABA: Make sure that we keep writing permissions ourselves,
+ // otherwise we can be in for a surprise on NFS.
+ fd = KDE_open(destC.data(), O_CREAT | O_TRUNC | O_WRONLY, -1==mode ? 0666 : mode | S_IWUSR | S_IRUSR);
+ }
+
+ if (fd < 0)
+ {
+ error(EACCES==errno ? KIO::ERR_WRITE_ACCESS_DENIED : KIO::ERR_CANNOT_OPEN_FOR_WRITING, dest);
+ return false;
+ }
+
+ int result;
+ // Loop until we got 0 (end of data)
+ do
+ {
+ QByteArray buffer;
+
+ dataReq(); // Request for data
+ result = readData(buffer);
+ if(result > 0 && !writeAll(fd, buffer.data(), buffer.size()))
+ {
+ if(ENOSPC==errno) // disk full
+ {
+ error(KIO::ERR_DISK_FULL, destOrig);
+ result = -2; // means: remove dest file
+ }
+ else
+ {
+ error(KIO::ERR_COULD_NOT_WRITE, destOrig);
+ result = -1;
+ }
+ }
+ }
+ while(result>0);
+
+ if (result<0)
+ {
+ close(fd);
+ if (-1==result)
+ ::remove(destC.data());
+ else if (markPartial)
+ {
+ KDE_struct_stat buff;
+
+ if ((-1==KDE_stat(destC.data(), &buff)) ||
+ (buff.st_size<config()->readNumEntry("MinimumKeepSize", DEFAULT_MINIMUM_KEEP_SIZE)))
+ ::remove(destC.data());
+ }
+ ::exit(255);
+ }
+
+ if (-1==fd) // we got nothing to write out, so we never opened the file
+ {
+ finished();
+ return false;
+ }
+
+ if (close(fd))
+ {
+ error(KIO::ERR_COULD_NOT_WRITE, destOrig);
+ return false;
+ }
+
+ // after full download rename the file back to original name
+ if (markPartial && ::rename(destC.data(), destOrigC.data()))
+ {
+ error(KIO::ERR_CANNOT_RENAME_PARTIAL, destOrig);
+ return false;
+ }
+
+ return true;
+}
+
+void CKioFonts::copy(const KURL &src, const KURL &d, int mode, bool overwrite)
+{
+ //
+ // Support:
+ // Copying to fonts:/
+ // Copying from fonts:/ and file:/
+ //
+ KFI_DBUG << "copy " << src.prettyURL() << " - " << d.prettyURL() << endl;
+
+ if(isHidden(d))
+ {
+ error(KIO::ERR_WRITE_ACCESS_DENIED, d.prettyURL());
+ return;
+ }
+
+ bool fromFonts=KFI_KIO_FONTS_PROTOCOL==src.protocol();
+
+ if((!fromFonts || updateFontList()) // CPD: dont update font list upon a copy from file - is too slow. Just stat on filename!
+ && checkUrl(src) && checkAllowed(src))
+ {
+ //checkUrl(u) // CPD as per comment in ::put()
+
+ QStringList srcFiles;
+
+ if(getSourceFiles(src, srcFiles)) // Any error will be logged in getSourceFiles
+ {
+ KURL dest(d);
+ bool changed=confirmUrl(dest);
+ EFolder destFolder(getFolder(dest));
+ QMap<QString, QString> map;
+
+ if(!fromFonts)
+ map[src.path()]=src.fileName();
+
+ // As above, if copying from file, then only stat on dest filename, but if from fonts to fonts need to
+ // get the list of possible source files, etc.
+ if(fromFonts ? confirmMultiple(src, srcFiles, FOLDER_SYS==destFolder ? FOLDER_USER : FOLDER_SYS, OP_COPY) &&
+ getFontList(srcFiles, map) &&
+ checkDestFiles(src, map, dest, destFolder, overwrite)
+ : checkDestFile(src, dest, destFolder, overwrite) )
+ {
+ if(nonRootSys(dest))
+ {
+ QCString cmd;
+ int size=0;
+
+ if(!Misc::dExists(itsFolders[destFolder].location))
+ {
+ cmd+="mkdir ";
+ cmd+=QFile::encodeName(KProcess::quote(itsFolders[destFolder].location));
+ cmd+=" && chmod 0755 ";
+ cmd+=QFile::encodeName(KProcess::quote(itsFolders[destFolder].location));
+ cmd+=" && ";
+ }
+
+ QMap<QString, QString>::Iterator fIt(map.begin()),
+ fEnd(map.end());
+
+ for(; fIt!=fEnd; ++fIt)
+ {
+ cmd+="cp -f ";
+ cmd+=QFile::encodeName(KProcess::quote(fIt.key()));
+ cmd+=" ";
+ cmd+=QFile::encodeName(KProcess::quote(itsFolders[destFolder].location+modifyName(fIt.data())));
+ int s=getSize(QFile::encodeName(fIt.key()));
+ if(s>0)
+ size+=s;
+ if(++fIt!=fEnd)
+ cmd+=" && ";
+ --fIt;
+ }
+
+ if(!itsCanStorePasswd)
+ createRootRefreshCmd(cmd);
+
+ totalSize(size);
+
+ QString passwd=getRootPasswd();
+
+ if(doRootCmd(cmd, passwd))
+ {
+ modified(destFolder);
+ processedSize(size);
+ if(src.isLocalFile() && 1==srcFiles.count())
+ createAfm(itsFolders[destFolder].location+modifyName(map.begin().data()), true, passwd);
+ }
+ else
+ {
+ error(KIO::ERR_SLAVE_DEFINED, i18n("Could not access \"%1\" folder.").arg(i18n(KFI_KIO_FONTS_SYS)));
+ return;
+ }
+ }
+ else
+ {
+ QMap<QString, QString>::Iterator fIt(map.begin()),
+ fEnd(map.end());
+
+ for(; fIt!=fEnd; ++fIt)
+ {
+ QCString realSrc(QFile::encodeName(fIt.key())),
+ realDest(QFile::encodeName(itsFolders[destFolder].location+modifyName(fIt.data())));
+ KDE_struct_stat buffSrc;
+
+ if(-1==KDE_stat(realSrc.data(), &buffSrc))
+ {
+ error(EACCES==errno ? KIO::ERR_ACCESS_DENIED : KIO::ERR_DOES_NOT_EXIST, src.prettyURL());
+ return;
+ }
+
+ int srcFd=KDE_open(realSrc.data(), O_RDONLY);
+
+ if (srcFd<0)
+ {
+ error(KIO::ERR_CANNOT_OPEN_FOR_READING, src.prettyURL());
+ return;
+ }
+
+ if(!Misc::dExists(itsFolders[destFolder].location))
+ Misc::createDir(itsFolders[destFolder].location);
+
+ // WABA: Make sure that we keep writing permissions ourselves,
+ // otherwise we can be in for a surprise on NFS.
+ int destFd=KDE_open(realDest.data(), O_CREAT | O_TRUNC | O_WRONLY, -1==mode ? 0666 : mode | S_IWUSR);
+
+ if (destFd<0)
+ {
+ error(EACCES==errno ? KIO::ERR_WRITE_ACCESS_DENIED : KIO::ERR_CANNOT_OPEN_FOR_WRITING, dest.prettyURL());
+ close(srcFd);
+ return;
+ }
+
+ totalSize(buffSrc.st_size);
+
+ KIO::filesize_t processed = 0;
+ char buffer[MAX_IPC_SIZE];
+ QByteArray array;
+
+ while(1)
+ {
+ int n=::read(srcFd, buffer, MAX_IPC_SIZE);
+
+ if(-1==n)
+ {
+ if (errno == EINTR)
+ continue;
+ error(KIO::ERR_COULD_NOT_READ, src.prettyURL());
+ close(srcFd);
+ close(destFd);
+ return;
+ }
+ if(0==n)
+ break; // Finished
+
+ if(!writeAll(destFd, buffer, n))
+ {
+ close(srcFd);
+ close(destFd);
+ if (ENOSPC==errno) // disk full
+ {
+ error(KIO::ERR_DISK_FULL, dest.prettyURL());
+ remove(realDest.data());
+ }
+ else
+ error(KIO::ERR_COULD_NOT_WRITE, dest.prettyURL());
+ return;
+ }
+
+ processed += n;
+ processedSize(processed);
+ }
+
+ close(srcFd);
+
+ if(close(destFd))
+ {
+ error(KIO::ERR_COULD_NOT_WRITE, dest.prettyURL());
+ return;
+ }
+
+ ::chmod(realDest.data(), Misc::FILE_PERMS);
+
+ // copy access and modification time
+ struct utimbuf ut;
+
+ ut.actime = buffSrc.st_atime;
+ ut.modtime = buffSrc.st_mtime;
+ ::utime(realDest.data(), &ut);
+
+ processedSize(buffSrc.st_size);
+ modified(destFolder);
+ }
+
+ if(src.isLocalFile() && 1==srcFiles.count())
+ createAfm(itsFolders[destFolder].location+modifyName(map.begin().data()));
+ }
+
+ finished();
+
+ if(changed)
+ itsLastDestTime=time(NULL);
+ }
+ }
+ }
+}
+
+void CKioFonts::rename(const KURL &src, const KURL &d, bool overwrite)
+{
+ KFI_DBUG << "rename " << src.prettyURL() << " - " << d.prettyURL() << ", " << overwrite << endl;
+
+ if(src.directory()==d.directory())
+ error(KIO::ERR_SLAVE_DEFINED, i18n("Sorry, fonts cannot be renamed."));
+ else if(itsRoot) // Should never happen...
+ error(KIO::ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(mProtocol, KIO::CMD_RENAME));
+ else
+ {
+ //
+ // Can't rename from/to file:/ -> therefore rename can only be from fonts:/System to fonts:/Personal,
+ // or vice versa.
+
+ QStringList srcFiles;
+
+ if(getSourceFiles(src, srcFiles)) // Any error will be logged in getSourceFiles
+ {
+ KURL dest(d);
+ bool changed=confirmUrl(dest);
+ EFolder destFolder(getFolder(dest));
+ QMap<QString, QString> map;
+
+ if(confirmMultiple(src, srcFiles, FOLDER_SYS==destFolder ? FOLDER_USER : FOLDER_SYS, OP_MOVE) &&
+ getFontList(srcFiles, map) &&
+ checkDestFiles(src, map, dest, destFolder, overwrite))
+ {
+ QMap<QString, QString>::Iterator fIt(map.begin()),
+ fEnd(map.end());
+ bool askPasswd=true,
+ toSys=FOLDER_SYS==destFolder;
+ QCString userId,
+ groupId,
+ destDir(QFile::encodeName(KProcess::quote(itsFolders[destFolder].location)));
+
+ userId.setNum(toSys ? 0 : getuid());
+ groupId.setNum(toSys ? 0 : getgid());
+
+ for(; fIt!=fEnd; ++fIt)
+ {
+ QCString cmd,
+ destFile(QFile::encodeName(KProcess::quote(itsFolders[destFolder].location+fIt.data())));
+
+ if(toSys && !Misc::dExists(itsFolders[destFolder].location))
+ {
+ cmd+="mkdir ";
+ cmd+=destDir;
+ cmd+=" && ";
+ }
+
+ cmd+="mv -f ";
+ cmd+=QFile::encodeName(KProcess::quote(fIt.key()));
+ cmd+=" ";
+ cmd+=destFile;
+ cmd+=" && chmod -f 0644 ";
+ cmd+=destFile;
+ cmd+=" && chown -f ";
+ cmd+=userId;
+ cmd+=":";
+ cmd+=groupId;
+ cmd+=" ";
+ cmd+=destFile;
+
+ QString sysDir,
+ userDir;
+
+ if(FOLDER_SYS==destFolder)
+ {
+ sysDir=itsFolders[destFolder].location;
+ userDir=Misc::getDir(fIt.key());
+ }
+ else
+ {
+ userDir=itsFolders[destFolder].location;
+ sysDir=Misc::getDir(fIt.key());
+ }
+
+ if(!itsCanStorePasswd)
+ createRootRefreshCmd(cmd, sysDir);
+
+ if(doRootCmd(cmd, askPasswd))
+ {
+ modified(FOLDER_SYS, true, sysDir);
+ modified(FOLDER_USER, true, userDir);
+ askPasswd=false; // Don't keep on asking for password...
+ }
+ else
+ {
+ error(KIO::ERR_SLAVE_DEFINED, i18n("Could not access \"%1\" folder.").arg(i18n(KFI_KIO_FONTS_SYS)));
+ return;
+ }
+ }
+ if(changed)
+ itsLastDestTime=time(NULL);
+ }
+ }
+ }
+}
+
+void CKioFonts::del(const KURL &url, bool)
+{
+ KFI_DBUG << "del " << url.path() << endl;
+
+ QValueList<FcPattern *> *entries;
+
+ if(checkUrl(url) && checkAllowed(url) &&
+ updateFontList() && (entries=getEntries(url)) && entries->count() &&
+ confirmMultiple(url, entries, getFolder(url), OP_DELETE))
+ {
+ QValueList<FcPattern *>::Iterator it,
+ end=entries->end();
+ CDirList modifiedDirs;
+ bool clearList=KFI_KIO_NO_CLEAR!=url.query();
+
+ if(nonRootSys(url))
+ {
+ QCString cmd("rm -f");
+
+ for(it=entries->begin(); it!=end; ++it)
+ {
+ QString file(CFcEngine::getFcString(*it, FC_FILE));
+
+ modifiedDirs.add(Misc::getDir(file));
+ cmd+=" ";
+ cmd+=QFile::encodeName(KProcess::quote(file));
+
+ KURL::List urls;
+
+ Misc::getAssociatedUrls(KURL(file), urls);
+
+ if(urls.count())
+ {
+ KURL::List::Iterator uIt,
+ uEnd=urls.end();
+
+ for(uIt=urls.begin(); uIt!=uEnd; ++uIt)
+ {
+ cmd+=" ";
+ cmd+=QFile::encodeName(KProcess::quote((*uIt).path()));
+ }
+ }
+ }
+
+ if(!itsCanStorePasswd)
+ createRootRefreshCmd(cmd, modifiedDirs);
+
+ if(doRootCmd(cmd))
+ modified(FOLDER_SYS, clearList, modifiedDirs);
+ else
+ error(KIO::ERR_SLAVE_DEFINED, i18n("Could not access \"%1\" folder.").arg(i18n(KFI_KIO_FONTS_SYS)));
+ }
+ else
+ {
+ for(it=entries->begin(); it!=end; ++it)
+ {
+ QString file(CFcEngine::getFcString(*it, FC_FILE));
+
+ if (0!=unlink(QFile::encodeName(file).data()))
+ error(EACCES==errno || EPERM==errno
+ ? KIO::ERR_ACCESS_DENIED
+ : EISDIR==errno
+ ? KIO::ERR_IS_DIRECTORY
+ : KIO::ERR_CANNOT_DELETE,
+ file);
+ else
+ {
+ modifiedDirs.add(Misc::getDir(file));
+
+ KURL::List urls;
+
+ Misc::getAssociatedUrls(KURL(file), urls);
+
+ if(urls.count())
+ {
+ KURL::List::Iterator uIt,
+ uEnd=urls.end();
+
+ for(uIt=urls.begin(); uIt!=uEnd; ++uIt)
+ unlink(QFile::encodeName((*uIt).path()).data());
+ }
+ }
+ }
+ modified(itsRoot ? FOLDER_SYS : FOLDER_USER, clearList, modifiedDirs);
+ }
+ finished();
+ }
+}
+
+void CKioFonts::modified(EFolder folder, bool clearList, const CDirList &dirs)
+{
+ KFI_DBUG << "modified(" << (int)folder << ")\n";
+
+ if(FOLDER_SYS!=folder || itsCanStorePasswd || itsRoot)
+ {
+ if(dirs.count())
+ {
+ CDirList::ConstIterator it(dirs.begin()),
+ end(dirs.end());
+
+ for(; it!=end; ++it)
+ itsFolders[folder].modified.add(*it);
+ }
+ else
+ itsFolders[folder].modified.add(itsFolders[folder].location);
+
+ if(++itsFontChanges>MAX_NEW_FONTS)
+ {
+ setTimeoutSpecialCommand(0); // Cancel timer
+ doModified();
+ }
+ else
+ setTimeoutSpecialCommand(TIMEOUT);
+ }
+
+ if(FOLDER_SYS==folder && !itsRoot && !itsCanStorePasswd)
+ {
+ // If we modified sys, we're not root, and couldn't store the passwd, then kfontinst has already been called
+ // so no need to ask it to add folder to fontconfig and X's config files...
+ itsHasSys=true;
+ itsAddToSysFc=false;
+ }
+ if(clearList)
+ clearFontList(); // List of fonts has changed.../
+}
+
+void CKioFonts::special(const QByteArray &a)
+{
+ KFI_DBUG << "special" << endl;
+
+ if(a.size())
+ {
+ QDataStream stream(a, IO_ReadOnly);
+ int cmd;
+
+ stream >> cmd;
+
+ switch (cmd)
+ {
+ case SPECIAL_RESCAN:
+ clearFontList();
+ updateFontList();
+ finished();
+ break;
+ case SPECIAL_RECONFIG: // Only itended to be called from kcmfontinst - when a user has re-enabled doX or doGs
+ if(itsRoot && !itsFolders[FOLDER_SYS].modified.contains(itsFolders[FOLDER_SYS].location))
+ itsFolders[FOLDER_SYS].modified.add(itsFolders[FOLDER_SYS].location);
+ else if(!itsRoot && !itsFolders[FOLDER_USER].modified.contains(itsFolders[FOLDER_USER].location))
+ itsFolders[FOLDER_USER].modified.add(itsFolders[FOLDER_USER].location);
+
+ doModified();
+ finished();
+ break;
+ default:
+ error( KIO::ERR_UNSUPPORTED_ACTION, QString::number(cmd));
+ }
+ }
+ else
+ doModified();
+}
+
+void CKioFonts::createRootRefreshCmd(QCString &cmd, const CDirList &dirs, bool reparseCfg)
+{
+ if(reparseCfg)
+ reparseConfig();
+
+ if(!cmd.isEmpty())
+ cmd+=" && ";
+
+ cmd+=FC_CACHE_CMD;
+
+ if(dirs.count())
+ {
+ CDirList::ConstIterator it(dirs.begin()),
+ end(dirs.end());
+
+ for(; it!=end; ++it)
+ {
+ QCString tmpCmd;
+
+ if(*it==itsFolders[FOLDER_SYS].location)
+ {
+ if(0!=itsNrsKfiParams[0])
+ tmpCmd+=itsNrsKfiParams;
+ }
+ else
+ if(0!=itsNrsNonMainKfiParams[0])
+ tmpCmd+=itsNrsNonMainKfiParams;
+
+ if(!tmpCmd.isEmpty())
+ {
+ cmd+=" && kfontinst ";
+ cmd+=tmpCmd;
+ cmd+=" ";
+ cmd+=QFile::encodeName(KProcess::quote(*it));
+ }
+ }
+ }
+ else if (0!=itsNrsKfiParams[0])
+ {
+ cmd+=" && kfontinst ";
+ cmd+=itsNrsKfiParams;
+ cmd+=" ";
+ cmd+=QFile::encodeName(KProcess::quote(itsFolders[FOLDER_SYS].location));
+ }
+}
+
+void CKioFonts::doModified()
+{
+ KFI_DBUG << "doModified" << endl;
+
+ if(itsFolders[FOLDER_SYS].modified.count() || itsFolders[FOLDER_USER].modified.count())
+ reparseConfig();
+
+ itsFontChanges=0;
+ if(itsFolders[FOLDER_SYS].modified.count())
+ {
+ if(itsRoot)
+ {
+ Misc::doCmd(FC_CACHE_CMD);
+ KFI_DBUG << "RUN(root): " << FC_CACHE_CMD << endl;
+
+ //
+ // If a non-default folder has been modified, always configure X
+ if(NULL==strchr(itsKfiParams, 'x') &&
+ (itsFolders[FOLDER_SYS].modified.count()>1 || !itsFolders[FOLDER_SYS].modified.contains(itsFolders[FOLDER_SYS].location)))
+ {
+ if(0==itsKfiParams[0])
+ strcpy(itsKfiParams, "-x");
+ else
+ strcat(itsKfiParams, "x");
+ }
+
+ if(0!=itsKfiParams[0])
+ {
+ CDirList::ConstIterator it(itsFolders[FOLDER_SYS].modified.begin()),
+ end(itsFolders[FOLDER_SYS].modified.end());
+
+ for(; it!=end; ++it)
+ {
+ Misc::doCmd("kfontinst", itsKfiParams, QFile::encodeName(*it));
+ KFI_DBUG << "RUN(root): kfontinst " << itsKfiParams << ' ' << *it << endl;
+ }
+
+ if(itsFolders[FOLDER_SYS].modified.contains(itsFolders[FOLDER_SYS].location))
+ {
+ itsHasSys=true;
+ itsAddToSysFc=false;
+ }
+ }
+ }
+ else
+ {
+ QCString cmd;
+
+ createRootRefreshCmd(cmd, itsFolders[FOLDER_SYS].modified, false);
+ if(doRootCmd(cmd, false) && itsFolders[FOLDER_SYS].modified.contains(itsFolders[FOLDER_SYS].location))
+ {
+ itsHasSys=true;
+ itsAddToSysFc=false;
+ }
+ if(NULL==strstr(itsNrsKfiParams, "s"))
+ Misc::doCmd("xset", "fp", "rehash"); // doRootCmd can only refresh if xfs is being used, so try here anyway...
+ }
+ itsFolders[FOLDER_SYS].modified.clear();
+ }
+
+ if(!itsRoot && itsFolders[FOLDER_USER].modified.count())
+ {
+ Misc::doCmd(FC_CACHE_CMD);
+ KFI_DBUG << "RUN(non-root): " << FC_CACHE_CMD << endl;
+
+ if(0!=itsKfiParams[0])
+ {
+ CDirList::ConstIterator it(itsFolders[FOLDER_USER].modified.begin()),
+ end(itsFolders[FOLDER_USER].modified.end());
+
+ for(; it!=end; ++it)
+ {
+ Misc::doCmd("kfontinst", itsKfiParams, QFile::encodeName(*it));
+ KFI_DBUG << "RUN(non-root): kfontinst " << itsKfiParams << ' ' << *it << endl;
+ }
+ }
+ itsFolders[FOLDER_USER].modified.clear();
+ }
+
+ KFI_DBUG << "finished ModifiedDirs" << endl;
+}
+
+#define SYS_USER "root"
+QString CKioFonts::getRootPasswd(bool askPasswd)
+{
+ KFI_DBUG << "getRootPasswd" << endl;
+ KIO::AuthInfo authInfo;
+ SuProcess proc(SYS_USER);
+ bool error=false;
+ int attempts=0;
+ QString errorMsg;
+
+ authInfo.url=KURL(KFI_KIO_FONTS_PROTOCOL ":///");
+ authInfo.username=SYS_USER;
+ authInfo.keepPassword=true;
+
+ if(!checkCachedAuthentication(authInfo) && !askPasswd)
+ authInfo.password=itsPasswd;
+
+ if(askPasswd)
+ while(!error && 0!=proc.checkInstall(authInfo.password.local8Bit()))
+ {
+ KFI_DBUG << "ATTEMPT : " << attempts << endl;
+ if(1==attempts)
+ errorMsg=i18n("Incorrect password.\n");
+ if((!openPassDlg(authInfo, errorMsg) && attempts) || ++attempts>4 || SYS_USER!=authInfo.username)
+ error=true;
+ }
+ else
+ error=proc.checkInstall(authInfo.password.local8Bit()) ? true : false;
+ return error ? QString::null : authInfo.password;
+}
+
+bool CKioFonts::doRootCmd(const char *cmd, const QString &passwd)
+{
+ KFI_DBUG << "doRootCmd " << cmd << endl;
+
+ if(!passwd.isEmpty())
+ {
+ SuProcess proc(SYS_USER);
+
+ if(itsCanStorePasswd)
+ itsPasswd=passwd;
+
+ KFI_DBUG << "Try to run command" << endl;
+ proc.setCommand(cmd);
+ return proc.exec(passwd.local8Bit()) ? false : true;
+ }
+
+ return false;
+}
+
+bool CKioFonts::confirmUrl(KURL &url)
+{
+ KFI_DBUG << "confirmUrl " << url.path() << endl;
+ if(!itsRoot)
+ {
+ QString sect(getSect(url.path()));
+
+ if(!isSysFolder(sect) && !isUserFolder(sect))
+ {
+ bool changeToSystem=false;
+
+ if(DEST_UNCHANGED!=itsLastDest && itsLastDestTime && (abs(time(NULL)-itsLastDestTime) < constMaxLastDestTime))
+ changeToSystem=DEST_SYS==itsLastDest;
+ else
+ changeToSystem=KMessageBox::No==messageBox(QuestionYesNo,
+ i18n("Do you wish to install the font into \"%1\" (in which "
+ "case the font will only be usable by you), or \"%2\" ("
+ "the font will be usable by all users - but you will "
+ "need to know the administrator's password)?")
+ .arg(i18n(KFI_KIO_FONTS_USER)).arg(i18n(KFI_KIO_FONTS_SYS)),
+ i18n("Where to Install"), i18n(KFI_KIO_FONTS_USER),
+ i18n(KFI_KIO_FONTS_SYS));
+
+ if(changeToSystem)
+ {
+ itsLastDest=DEST_SYS;
+ url.setPath(QChar('/')+i18n(KFI_KIO_FONTS_SYS)+QChar('/')+url.fileName());
+ }
+ else
+ {
+ itsLastDest=DEST_USER;
+ url.setPath(QChar('/')+i18n(KFI_KIO_FONTS_USER)+QChar('/')+url.fileName());
+ }
+
+ KFI_DBUG << "Changed URL to:" << url.path() << endl;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void CKioFonts::clearFontList()
+{
+ KFI_DBUG << "clearFontList" << endl;
+
+ if(itsFontList)
+ FcFontSetDestroy(itsFontList);
+
+ itsFontList=NULL;
+ itsFolders[FOLDER_SYS].fontMap.clear();
+ itsFolders[FOLDER_USER].fontMap.clear();
+}
+
+bool CKioFonts::updateFontList()
+{
+ KFI_DBUG << "updateFontList" << endl;
+
+ if(!itsFontList || !FcConfigUptoDate(0) || // For some reason just the "!FcConfigUptoDate(0)" check does not always work :-(
+ (abs(time(NULL)-itsLastFcCheckTime)>constMaxFcCheckTime))
+ {
+ FcInitReinitialize();
+ clearFontList();
+ }
+
+ if(!itsFontList)
+ {
+ KFI_DBUG << "updateFontList - update list of fonts " << endl;
+
+ itsLastFcCheckTime=time(NULL);
+
+ FcPattern *pat = FcPatternCreate();
+ FcObjectSet *os = FcObjectSetBuild(FC_FILE, FC_FAMILY, FC_WEIGHT, FC_SCALABLE,
+#ifdef KFI_FC_HAS_WIDTHS
+ FC_WIDTH,
+#endif
+ FC_SLANT, (void*)0);
+
+ itsFontList=FcFontList(0, pat, os);
+
+ FcPatternDestroy(pat);
+ FcObjectSetDestroy(os);
+
+ if (itsFontList)
+ {
+ QString home(Misc::dirSyntax(QDir::homeDirPath()));
+
+ for (int i = 0; i < itsFontList->nfont; i++)
+ {
+ EFolder folder=FOLDER_SYS;
+ QString file(Misc::fileSyntax(CFcEngine::getFcString(itsFontList->fonts[i], FC_FILE)));
+
+ if(!file.isEmpty())
+ {
+ if(!itsRoot && 0==file.find(home))
+ folder=FOLDER_USER;
+
+ QValueList<FcPattern *> &patterns=
+ itsFolders[folder].fontMap[CFcEngine::createName(itsFontList->fonts[i])];
+ bool use=true;
+
+ if(patterns.count()) // Check for duplicates...
+ {
+ QValueList<FcPattern *>::Iterator it,
+ end=patterns.end();
+
+ for(it=patterns.begin(); use && it!=end; ++it)
+ if(file==(Misc::fileSyntax(CFcEngine::getFcString(*it, FC_FILE))))
+ use=false;
+ }
+ if(use)
+ patterns.append(itsFontList->fonts[i]);
+ }
+ }
+ }
+ }
+
+ if(NULL==itsFontList)
+ {
+ error(KIO::ERR_SLAVE_DEFINED, i18n("Internal fontconfig error."));
+ return false;
+ }
+
+ return true;
+}
+
+CKioFonts::EFolder CKioFonts::getFolder(const KURL &url)
+{
+ return itsRoot || isSysFolder(getSect(url.path())) ? FOLDER_SYS : FOLDER_USER;
+}
+
+QMap<QString, QValueList<FcPattern *> >::Iterator CKioFonts::getMap(const KURL &url)
+{
+ EFolder folder(getFolder(url));
+ QMap<QString, QValueList<FcPattern *> >::Iterator it=itsFolders[folder].fontMap.find(removeMultipleExtension(url));
+
+ if(it==itsFolders[folder].fontMap.end()) // Perhaps it was fonts:/System/times.ttf ???
+ {
+ FcPattern *pat=getEntry(folder, url.fileName(), false);
+
+ if(pat)
+ it=itsFolders[folder].fontMap.find(CFcEngine::createName(pat));
+ }
+
+ return it;
+}
+
+QValueList<FcPattern *> * CKioFonts::getEntries(const KURL &url)
+{
+ QMap<QString, QValueList<FcPattern *> >::Iterator it=getMap(url);
+
+ if(it!=itsFolders[getFolder(url)].fontMap.end())
+ return &(it.data());
+
+ error(KIO::ERR_SLAVE_DEFINED, i18n("Could not access \"%1\".").arg(url.prettyURL()));
+ return NULL;
+}
+
+FcPattern * CKioFonts::getEntry(EFolder folder, const QString &file, bool full)
+{
+ QMap<QString, QValueList<FcPattern *> >::Iterator it,
+ end=itsFolders[folder].fontMap.end();
+
+ for(it=itsFolders[folder].fontMap.begin(); it!=end; ++it)
+ {
+ QValueList<FcPattern *>::Iterator patIt,
+ patEnd=it.data().end();
+
+ for(patIt=it.data().begin(); patIt!=patEnd; ++patIt)
+ if( (full && CFcEngine::getFcString(*patIt, FC_FILE)==file) ||
+ (!full && Misc::getFile(CFcEngine::getFcString(*patIt, FC_FILE))==file))
+ return *patIt;
+ }
+
+ return NULL;
+}
+
+bool CKioFonts::checkFile(const QString &file)
+{
+ QCString cFile(QFile::encodeName(file));
+
+ //
+ // To speed things up, check the files extension 1st...
+ if(checkExt(cFile, "ttf") || checkExt(cFile, "otf") || checkExt(cFile, "ttc") || checkExt(cFile, "pfa") || checkExt(cFile, "pfb") ||
+ isAAfm(file) || isAPfm(file))
+ return true;
+
+ //
+ // No exension match, so try querying with FreeType...
+ int count=0;
+ FcPattern *pat=FcFreeTypeQuery((const FcChar8 *)(QFile::encodeName(file).data()), 0, NULL, &count);
+
+ if(pat)
+ {
+ FcPatternDestroy(pat);
+ return true;
+ }
+
+ error(KIO::ERR_SLAVE_DEFINED, i18n("<p>Only fonts may be installed.</p><p>If installing a fonts package (*%1), then "
+ "extract the components, and install individually.</p>").arg(constMultipleExtension));
+ return false;
+}
+
+bool CKioFonts::getSourceFiles(const KURL &src, QStringList &files)
+{
+ if(KFI_KIO_FONTS_PROTOCOL==src.protocol())
+ {
+ QValueList<FcPattern *> *entries=getEntries(src);
+
+ if(entries && entries->count())
+ {
+ QValueList<FcPattern *>::Iterator it,
+ end=entries->end();
+
+ for(it=entries->begin(); it!=end; ++it)
+ files.append(CFcEngine::getFcString(*it, FC_FILE));
+ }
+
+ if(files.count())
+ {
+ QStringList::Iterator sIt,
+ sEnd=files.end();
+
+ for(sIt=files.begin(); sIt!=sEnd; ++sIt)
+ {
+ KURL::List urls;
+
+ Misc::getAssociatedUrls(KURL(*sIt), urls);
+
+ if(urls.count())
+ {
+ KURL::List::Iterator uIt,
+ uEnd=urls.end();
+
+ for(uIt=urls.begin(); uIt!=uEnd; ++uIt)
+ if(-1==files.findIndex((*uIt).path()))
+ files.append((*uIt).path());
+ }
+ }
+ }
+ }
+ else
+ if(src.isLocalFile())
+ if(checkFile(src.path()))
+ files.append(src.path());
+ else
+ return false; // error logged in checkFile...
+
+ if(files.count())
+ {
+ QStringList::Iterator it,
+ end=files.end();
+
+ for(it=files.begin(); it!=end; ++it)
+ {
+ QCString realSrc=QFile::encodeName(*it);
+ KDE_struct_stat buffSrc;
+
+ if (-1==KDE_stat(realSrc.data(), &buffSrc))
+ {
+ error(EACCES==errno ? KIO::ERR_ACCESS_DENIED : KIO::ERR_DOES_NOT_EXIST, src.prettyURL());
+ return false;
+ }
+ if(S_ISDIR(buffSrc.st_mode))
+ {
+ error(KIO::ERR_IS_DIRECTORY, src.prettyURL());
+ return false;
+ }
+ if(S_ISFIFO(buffSrc.st_mode) || S_ISSOCK(buffSrc.st_mode))
+ {
+ error(KIO::ERR_CANNOT_OPEN_FOR_READING, src.prettyURL());
+ return false;
+ }
+ }
+ }
+ else
+ {
+ error(KIO::ERR_DOES_NOT_EXIST, src.prettyURL());
+ return false;
+ }
+
+ return true;
+}
+
+bool CKioFonts::checkDestFile(const KURL &src, const KURL &dest, EFolder destFolder, bool overwrite)
+{
+ if(!overwrite && (Misc::fExists(itsFolders[destFolder].location+src.fileName()) ||
+ Misc::fExists(itsFolders[destFolder].location+modifyName(src.fileName())) ) )
+ {
+ error(KIO::ERR_FILE_ALREADY_EXIST, dest.prettyURL());
+ return false;
+ }
+
+ return true;
+}
+
+bool CKioFonts::checkDestFiles(const KURL &src, QMap<QString, QString> &map, const KURL &dest, EFolder destFolder, bool overwrite)
+{
+ //
+ // Check whether files exist at destination...
+ //
+ if(dest.protocol()==src.protocol() &&
+ dest.directory()==src.directory()) // Check whether confirmUrl changed a "cp fonts:/System fonts:/"
+ // to "cp fonts:/System fonts:/System"
+ {
+ error(KIO::ERR_FILE_ALREADY_EXIST, dest.prettyURL());
+ return false;
+ }
+
+ if(!overwrite)
+ {
+ QMap<QString, QString>::Iterator fIt(map.begin()),
+ fEnd(map.end());
+
+ for(; fIt!=fEnd; ++fIt)
+ if(NULL!=getEntry(destFolder, fIt.data()) || NULL!=getEntry(destFolder, modifyName(fIt.data())))
+ {
+ error(KIO::ERR_FILE_ALREADY_EXIST, dest.prettyURL());
+ return false;
+ }
+ }
+
+ return true;
+}
+
+//
+// Gather the number and names of the font faces located in "files". If there is more than 1 face
+// (such as there would be for a TTC font), then ask the user for confirmation of the action.
+bool CKioFonts::confirmMultiple(const KURL &url, const QStringList &files, EFolder folder, EOp op)
+{
+ if(KFI_KIO_FONTS_PROTOCOL!=url.protocol())
+ return true;
+
+ QStringList::ConstIterator it,
+ end=files.end();
+ QStringList fonts;
+
+ for(it=files.begin(); it!=files.end(); ++it)
+ {
+ FcPattern *pat=getEntry(folder, *it, false);
+
+ if(pat)
+ {
+ QString name(CFcEngine::createName(pat));
+
+ if(-1==fonts.findIndex(name))
+ fonts.append(name);
+ }
+ }
+
+ if(fonts.count()>1)
+ {
+ QString out;
+ QStringList::Iterator it,
+ end=fonts.end();
+
+ for(it=fonts.begin(); it!=end; ++it)
+ out+=QString("<li>")+*it+QString("</li>");
+
+ if(KMessageBox::No==messageBox(QuestionYesNo,
+ OP_MOVE==op
+ ? i18n("<p>This font is located in a file alongside other fonts; in order "
+ "to proceed with the moving they will all have to be moved. "
+ "The other affected fonts are:</p><ul>%1</ul><p>\n Do you wish to "
+ "move all of these?</p>").arg(out)
+ : OP_COPY==op
+ ? i18n("<p>This font is located in a file alongside other fonts; in order "
+ "to proceed with the copying they will all have to be copied. "
+ "The other affected fonts are:</p><ul>%1</ul><p>\n Do you wish to "
+ "copy all of these?</p>").arg(out)
+ : i18n("<p>This font is located in a file alongside other fonts; in order "
+ "to proceed with the deleting they will all have to be deleted. "
+ "The other affected fonts are:</p><ul>%1</ul><p>\n Do you wish to "
+ "delete all of these?</p>").arg(out)))
+ {
+ error(KIO::ERR_USER_CANCELED, url.prettyURL());
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool CKioFonts::confirmMultiple(const KURL &url, QValueList<FcPattern *> *patterns, EFolder folder, EOp op)
+{
+ if(KFI_KIO_FONTS_PROTOCOL!=url.protocol())
+ return true;
+
+ QStringList files;
+
+ if(patterns && patterns->count())
+ {
+ QValueList<FcPattern *>::Iterator it,
+ end=patterns->end();
+
+ for(it=patterns->begin(); it!=end; ++it)
+ files.append(CFcEngine::getFcString(*it, FC_FILE));
+ }
+
+ return confirmMultiple(url, files, folder, op);
+}
+
+bool CKioFonts::checkUrl(const KURL &u, bool rootOk)
+{
+ if(KFI_KIO_FONTS_PROTOCOL==u.protocol() && (!rootOk || (rootOk && "/"!=u.path())))
+ {
+ QString sect(getSect(u.path()));
+
+ if(itsRoot)
+ {
+ if((isSysFolder(sect) || isUserFolder(sect)) &&
+ (itsFolders[FOLDER_SYS].fontMap.end()==itsFolders[FOLDER_SYS].fontMap.find(sect)))
+//CPD: TODO: || it has a font specified! e.g. fonts:/System/Times -> even in have a fonts:/System font, redirect
+//should still happen
+ {
+ redirection(getRedirect(u));
+ finished();
+ return false;
+ }
+ }
+ else
+ if(!isSysFolder(sect) && !isUserFolder(sect))
+ {
+ error(KIO::ERR_SLAVE_DEFINED, i18n("Please specify \"%1\" or \"%2\".")
+ .arg(i18n(KFI_KIO_FONTS_USER)).arg(i18n(KFI_KIO_FONTS_SYS)));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool CKioFonts::checkAllowed(const KURL &u)
+{
+ if (KFI_KIO_FONTS_PROTOCOL==u.protocol())
+ {
+ QString ds(Misc::dirSyntax(u.path()));
+
+ if(ds==QString(QChar('/')+i18n(KFI_KIO_FONTS_USER)+QChar('/')) ||
+ ds==QString(QChar('/')+i18n(KFI_KIO_FONTS_SYS)+QChar('/')) ||
+ ds==QString(QChar('/')+QString::fromLatin1(KFI_KIO_FONTS_USER)+QChar('/')) ||
+ ds==QString(QChar('/')+QString::fromLatin1(KFI_KIO_FONTS_SYS)+QChar('/')))
+ {
+ error(KIO::ERR_SLAVE_DEFINED, i18n("Sorry, you cannot rename, move, copy, or delete either \"%1\" or \"%2\".")
+ .arg(i18n(KFI_KIO_FONTS_USER)).arg(i18n(KFI_KIO_FONTS_SYS))); \
+ return false;
+ }
+ }
+
+ return true;
+}
+
+//
+// Create an AFM from a Type 1 (pfa/pfb) font and its PFM file...
+void CKioFonts::createAfm(const QString &file, bool nrs, const QString &passwd)
+{
+ if(nrs && passwd.isEmpty())
+ return;
+
+ bool type1=isAType1(file),
+ pfm=!type1 && isAPfm(file); // No point checking if is pfm if its a type1
+
+ if(type1 || pfm)
+ {
+ QString afm=getMatch(file, "afm"); // pf2afm wants files with lowercase extension, so just check for lowercase!
+ // -- when a font is installed, the extensio is converted to lowercase anyway...
+
+ if(afm.isEmpty()) // No point creating if AFM already exists!
+ {
+ QString pfm,
+ t1;
+
+ if(type1) // Its a Type1, so look for existing PFM
+ {
+ pfm=getMatch(file, "pfm");
+ t1=file;
+ }
+ else // Its a PFM, so look for existing Type1
+ {
+ t1=getMatch(file, "pfa");
+ if(t1.isEmpty())
+ t1=getMatch(file, "pfb");
+ pfm=file;
+ }
+
+ if(!t1.isEmpty() && !pfm.isEmpty()) // Do we have both Type1 and PFM?
+ {
+ QString name(t1.left(t1.length()-4)); // pf2afm wants name without extension...
+
+ if(nrs)
+ {
+ QCString cmd("pf2afm ");
+ cmd+=QFile::encodeName(KProcess::quote(name));
+ doRootCmd(cmd, passwd);
+ }
+ else
+ Misc::doCmd("pf2afm", QFile::encodeName(name));
+ }
+ }
+ }
+}
+
+void CKioFonts::reparseConfig()
+{
+ KFI_DBUG << "reparseConfig" << endl;
+
+ itsKfiParams[0]=0;
+ if(!itsRoot)
+ {
+ itsNrsKfiParams[0]=0;
+ itsNrsNonMainKfiParams[0]=0;
+ }
+
+ if(itsRoot)
+ {
+ KConfig cfg(KFI_ROOT_CFG_FILE);
+ bool doX=cfg.readBoolEntry(KFI_CFG_X_KEY, KFI_DEFAULT_CFG_X),
+ doGs=cfg.readBoolEntry(KFI_CFG_GS_KEY, KFI_DEFAULT_CFG_GS);
+
+ if(doX || !doGs)
+ {
+ strcpy(itsKfiParams, doGs ? "-g" : "-");
+ if(doX)
+ {
+ if(!itsUsingXfsFpe)
+ strcat(itsKfiParams, "r");
+
+ if(!itsUsingFcFpe)
+ {
+ strcat(itsKfiParams, itsUsingXfsFpe ? "sx" : "x");
+ if(!itsHasSys)
+ strcat(itsKfiParams, "a");
+ }
+ }
+ }
+ }
+ else
+ {
+ KConfig rootCfg(KFI_ROOT_CFG_FILE);
+ bool rootDoX=rootCfg.readBoolEntry(KFI_CFG_X_KEY, KFI_DEFAULT_CFG_X),
+ rootDoGs=rootCfg.readBoolEntry(KFI_CFG_GS_KEY, KFI_DEFAULT_CFG_GS);
+
+ strcpy(itsNrsKfiParams, "-");
+
+ if(rootDoX || rootDoGs)
+ {
+ strcpy(itsNrsKfiParams, "-");
+ strcpy(itsNrsNonMainKfiParams, "-");
+
+ if(rootDoGs)
+ {
+ strcpy(itsNrsKfiParams, "g");
+ strcpy(itsNrsNonMainKfiParams, "g");
+ }
+
+ if(rootDoX && !itsUsingFcFpe)
+ {
+ strcat(itsNrsKfiParams, itsUsingXfsFpe ? "sx" : "x"); // Can't get root to refresh X, only xfs!
+ strcat(itsNrsNonMainKfiParams, itsUsingXfsFpe ? "sx" : "x");
+ if(!itsHasSys)
+ strcat(itsNrsKfiParams, "a");
+ }
+ if(0==itsNrsNonMainKfiParams[1])
+ itsNrsNonMainKfiParams[0]=0;
+ }
+
+ if(itsAddToSysFc)
+ strcpy(itsNrsKfiParams, "f");
+
+ if(0==itsNrsKfiParams[1])
+ itsNrsKfiParams[0]=0;
+
+ KConfig cfg(KFI_CFG_FILE);
+ bool doX=cfg.readBoolEntry(KFI_CFG_X_KEY, KFI_DEFAULT_CFG_X),
+ doGs=cfg.readBoolEntry(KFI_CFG_GS_KEY, KFI_DEFAULT_CFG_GS);
+
+ strcpy(itsKfiParams, doGs ? "-g" : "-");
+
+ if(doX)
+ strcat(itsKfiParams, itsUsingFcFpe ? "r" : "rx");
+ }
+
+ if(0==itsKfiParams[1])
+ itsKfiParams[0]=0;
+}
+
+}
diff --git a/kcontrol/kfontinst/kio/KioFonts.h b/kcontrol/kfontinst/kio/KioFonts.h
new file mode 100644
index 000000000..abfd6b042
--- /dev/null
+++ b/kcontrol/kfontinst/kio/KioFonts.h
@@ -0,0 +1,161 @@
+#ifndef __KIO_FONTS_H__
+#define __KIO_FONTS_H__
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : KFI::CKioFonts
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 05/03/2003
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2003, 2004
+////////////////////////////////////////////////////////////////////////////////
+
+#include <fontconfig/fontconfig.h>
+#include <time.h>
+#include <kio/slavebase.h>
+#include <kurl.h>
+#include <klocale.h>
+#include <qstring.h>
+#include <qcstring.h>
+#include <qmap.h>
+#include <qvaluelist.h>
+#include "Misc.h"
+#include "KfiConstants.h"
+
+namespace KFI
+{
+
+class CKioFonts : public KIO::SlaveBase
+{
+ private:
+
+ enum EConstants
+ {
+ KFI_PARAMS = 8
+ };
+
+ enum EDest
+ {
+ DEST_UNCHANGED,
+ DEST_SYS,
+ DEST_USER
+ };
+
+ enum EFolder
+ {
+ FOLDER_SYS,
+ FOLDER_USER,
+
+ FOLDER_COUNT
+ };
+
+ enum EOp
+ {
+ OP_COPY,
+ OP_MOVE,
+ OP_DELETE
+ };
+
+ class CDirList : public QStringList
+ {
+ public:
+
+ CDirList() { }
+ CDirList(const QString &str) : QStringList(str) { }
+
+ void add(const QString &d) { if (!contains(d)) append(d); }
+ };
+
+ struct TFolder
+ {
+ QString location;
+ CDirList modified;
+ QMap<QString, QValueList<FcPattern *> > fontMap; // Maps from "Times New Roman" -> $HOME/.fonts/times.ttf
+ };
+
+ public:
+
+ CKioFonts(const QCString &pool, const QCString &app);
+ virtual ~CKioFonts();
+
+ static QString getSect(const QString &f) { return f.section('/', 1, 1); }
+
+ void listDir(const KURL &url);
+ void stat(const KURL &url);
+ bool createStatEntry(KIO::UDSEntry &entry, const KURL &url, EFolder folder);
+ void get(const KURL &url);
+ void put(const KURL &url, int mode, bool overwrite, bool resume);
+ void copy(const KURL &src, const KURL &dest, int mode, bool overwrite);
+ void rename(const KURL &src, const KURL &dest, bool overwrite);
+ void del(const KURL &url, bool isFile);
+
+ private:
+
+ bool putReal(const QString &destOrig, const QCString &destOrigC, bool origExists, int mode, bool resume);
+ void modified(EFolder folder, bool clearList=true, const CDirList &dirs=CDirList());
+ void special(const QByteArray &a);
+ void createRootRefreshCmd(QCString &cmd, const CDirList &dirs=CDirList(), bool reparseCfg=true);
+ void doModified();
+ QString getRootPasswd(bool askPasswd=true);
+ bool doRootCmd(const char *cmd, const QString &passwd);
+ bool doRootCmd(const char *cmd, bool askPasswd=true) { return doRootCmd(cmd, getRootPasswd(askPasswd)); }
+ bool confirmUrl(KURL &url);
+ void clearFontList();
+ bool updateFontList();
+ EFolder getFolder(const KURL &url);
+ QMap<QString, QValueList<FcPattern *> >::Iterator getMap(const KURL &url);
+ QValueList<FcPattern *> * getEntries(const KURL &url);
+ FcPattern * getEntry(EFolder folder, const QString &file, bool full=false);
+ bool checkFile(const QString &file);
+ bool getSourceFiles(const KURL &src, QStringList &files);
+ bool checkDestFile(const KURL &src, const KURL &dest, EFolder destFolder, bool overwrite);
+ bool checkDestFiles(const KURL &src, QMap<QString, QString> &map, const KURL &dest, EFolder destFolder, bool overwrite);
+ bool confirmMultiple(const KURL &url, const QStringList &files, EFolder folder, EOp op);
+ bool confirmMultiple(const KURL &url, QValueList<FcPattern *> *patterns, EFolder folder, EOp op);
+ bool checkUrl(const KURL &u, bool rootOk=false);
+ bool checkAllowed(const KURL &u);
+ void createAfm(const QString &file, bool nrs=false, const QString &passwd=QString::null);
+ void reparseConfig();
+
+ private:
+
+ bool itsRoot,
+ itsCanStorePasswd,
+ itsUsingFcFpe,
+ itsUsingXfsFpe,
+ itsHasSys,
+ itsAddToSysFc;
+ QString itsPasswd;
+ unsigned int itsFontChanges;
+ EDest itsLastDest;
+ time_t itsLastDestTime,
+ itsLastFcCheckTime;
+ FcFontSet *itsFontList;
+ TFolder itsFolders[FOLDER_COUNT];
+ char itsNrsKfiParams[KFI_PARAMS],
+ itsNrsNonMainKfiParams[KFI_PARAMS],
+ itsKfiParams[KFI_PARAMS];
+};
+
+}
+
+#endif
diff --git a/kcontrol/kfontinst/kio/Makefile.am b/kcontrol/kfontinst/kio/Makefile.am
new file mode 100644
index 000000000..ad0f2ea8e
--- /dev/null
+++ b/kcontrol/kfontinst/kio/Makefile.am
@@ -0,0 +1,20 @@
+kde_module_LTLIBRARIES = kio_fonts.la
+kio_fonts_la_SOURCES = \
+KioFonts.cpp
+
+kio_fonts_la_LIBADD = ../../fonts/libkxftconfig.la $(LIBFONTCONFIG_LIBS) $(LIBFREETYPE_LIBS) $(LIB_KIO) -lkdesu ../lib/libkfontinst.la
+kio_fonts_la_LDFLAGS = $(KDE_PLUGIN) $(all_libraries) $(KDE_RPATH) $(LIBFONTCONFIG_RPATH) $(LIBFREETYPE_RPATH) -module -avoid-version -no-undefined
+AM_CPPFLAGS= -I$(srcdir)/../lib -I$(srcdir)/../../fonts $(all_includes) $(LIBFREETYPE_CFLAGS) $(LIBFONTCONFIG_CFLAGS) -D_LARGEFILE64_SOURCE
+
+# The kxftconfig stuf really belongs to kdebase/kcontrol/fonts - here only so that can distribute this as an archive.
+noinst_HEADERS = \
+KioFonts.h
+
+servicesdir = $(kde_servicesdir)
+services_DATA = fonts.protocol
+
+vfsdata_DATA = fonts.desktop
+vfsdatadir = $(kde_datadir)/konqsidebartng/virtual_folders/services
+
+mimetype_DATA = folder.desktop system-folder.desktop package.desktop
+mimetypedir = $(kde_mimedir)/fonts
diff --git a/kcontrol/kfontinst/kio/folder.desktop b/kcontrol/kfontinst/kio/folder.desktop
new file mode 100644
index 000000000..24e328ae8
--- /dev/null
+++ b/kcontrol/kfontinst/kio/folder.desktop
@@ -0,0 +1,80 @@
+[Desktop Entry]
+Comment=Fonts Folder
+Comment[af]=Skrif tipe Gids
+Comment[ar]=مجلد المحارف
+Comment[be]=Тэчка шрыфтоў
+Comment[bg]=Директория за шрифтове
+Comment[bn]=ফন্ট ফোল্ডার
+Comment[br]=Renkell ar fontoù
+Comment[bs]=Direktorij sa fontovima
+Comment[ca]=Carpeta de lletres
+Comment[cs]=Složka písem
+Comment[csb]=Katalog fòntów
+Comment[da]=Skrifttypemappe
+Comment[de]=Ordner für Schriftarten
+Comment[el]=Φάκελος γραμματοσειρών
+Comment[eo]=Tipardosierujo
+Comment[es]=Carpeta de tipos de letra
+Comment[et]=Fontide kataloog
+Comment[eu]=Letra-tipoen karpeta
+Comment[fa]=پوشۀ قلم
+Comment[fi]=Kirjasinkansio
+Comment[fr]=Dossier de polices de caractères
+Comment[fy]=Lettertypenmap
+Comment[ga]=Fillteán na gClónna
+Comment[gl]=Cartafol das Fontes
+Comment[he]=תיקיית גופנים
+Comment[hi]=फ़ॉन्ट्स फ़ोल्डर
+Comment[hr]=Mapa fontova
+Comment[hu]=Betűtípuskönyvtár
+Comment[id]=Folder Fonts
+Comment[is]=Leturmappa
+Comment[it]=Cartella dei caratteri
+Comment[ja]=フォントフォルダ
+Comment[ka]=ფონტების საქაღალდე
+Comment[kk]=Қаріп қапшығы
+Comment[km]=ថត​ពុម្ពអក្សរ
+Comment[ko]=홈 폴더
+Comment[lt]=Šriftų aplankas
+Comment[lv]=Fontu mape
+Comment[mk]=Папка со фонтови
+Comment[ms]=Folder Fon
+Comment[mt]=Direttorju tal-fonts
+Comment[nb]=Mappe for skrifttyper
+Comment[nds]=Schriftoorden-Orner
+Comment[ne]=फन्ट फोल्डर
+Comment[nl]=Lettertypenmap
+Comment[nn]=Skriftmappe
+Comment[pa]=ਫੋਂਟ ਫੋਲਡਰ
+Comment[pl]=Katalog czcionek
+Comment[pt]=Pasta de Tipos de Letra
+Comment[pt_BR]=Pasta de Fontes
+Comment[ro]=Folder de fonturi
+Comment[ru]=Папка шрифтов
+Comment[rw]=Ububiko bw'Imyandikire
+Comment[se]=Fontamáhppa
+Comment[sk]=Priečinok písiem
+Comment[sl]=Mapa za pisave
+Comment[sr]=Фасцикла за фонтове
+Comment[sr@Latn]=Fascikla za fontove
+Comment[sv]=Teckensnittskatalog
+Comment[ta]=எழுத்துருக்கள் அடைவு
+Comment[tg]=Феҳристи ҳарфҳо
+Comment[th]=โฟลเดอร์แฟ้มแบบอักษร
+Comment[tr]=Yazıtipi Klasörü
+Comment[tt]=Yazu lar Törgäge
+Comment[uk]=Тека шрифтів
+Comment[uz]=Shriftlarning jildi
+Comment[uz@cyrillic]=Шрифтларнинг жилди
+Comment[vi]=Thư mục Phông chữ
+Comment[wa]=Ridant di fontes
+Comment[zh_CN]=字体文件夹
+Comment[zh_TW]=字型資料夾
+Icon=folder
+Type=MimeType
+MimeType=fonts/folder
+Patterns=
+
+X-KDE-AutoEmbed=true
+X-KDE-IsAlso=inode/directory
+
diff --git a/kcontrol/kfontinst/kio/fonts.desktop b/kcontrol/kfontinst/kio/fonts.desktop
new file mode 100644
index 000000000..0095f49d2
--- /dev/null
+++ b/kcontrol/kfontinst/kio/fonts.desktop
@@ -0,0 +1,85 @@
+[Desktop Entry]
+Type=Link
+URL=fonts:/
+Icon=fonts
+Name=Fonts
+Name[af]=Skriftipes
+Name[ar]=المحارف
+Name[az]=Yazı növləri
+Name[be]=Шрыфты
+Name[bg]=Шрифтове
+Name[bn]=ফন্ট
+Name[br]=Fontoù
+Name[bs]=Fontovi
+Name[ca]=Lletres
+Name[cs]=Písma
+Name[csb]=Fòntë
+Name[cy]=Ffontiau
+Name[da]=Skrifttyper
+Name[de]=Schriftarten
+Name[el]=Γραμματοσειρές
+Name[eo]=Tiparoj
+Name[es]=Tipos de letra
+Name[et]=Fondid
+Name[eu]=Letra-tipoak
+Name[fa]=قلمها
+Name[fi]=Kirjasimet
+Name[fr]=Polices
+Name[fy]=Lettertypen
+Name[ga]=Clónna
+Name[gl]=Fontes
+Name[he]=גופנים
+Name[hi]=फ़ॉन्ट्स
+Name[hr]=Fontovi
+Name[hu]=Betűtípusok
+Name[is]=Letur
+Name[it]=Tipi di carattere
+Name[ja]=フォント
+Name[ka]=ფონტები
+Name[kk]=Қаріптер
+Name[km]=ពុម្ពអក្សរ
+Name[ko]=글꼴
+Name[lo]=ຮູບແບບຕົວອັກສອນ
+Name[lt]=Šriftai
+Name[lv]=Fonti
+Name[mk]=Фонтови
+Name[mn]=Бичгүүд
+Name[ms]=Fon
+Name[nb]=Skrifttype
+Name[nds]=Schriftoorden
+Name[ne]=फन्ट
+Name[nl]=Lettertypen
+Name[nn]=Skrifttypar
+Name[nso]=Difonto
+Name[pa]=ਫੋਂਟ
+Name[pl]=Czcionki
+Name[pt]=Tipos de Letra
+Name[pt_BR]=Fontes
+Name[ro]=Fonturi
+Name[ru]=Шрифты
+Name[rw]=Imyandikire
+Name[se]=Fonttat
+Name[sk]=Písma
+Name[sl]=Pisave
+Name[sr]=Фонтови
+Name[sr@Latn]=Fontovi
+Name[ss]=Timo tetinhlamvu temagama
+Name[sv]=Teckensnitt
+Name[ta]=எழுத்துருக்கள்
+Name[tg]=Ҳарфҳо
+Name[th]=แบบอักษร
+Name[tr]=Yazıtipleri
+Name[tt]=Yazu
+Name[uk]=Шрифти
+Name[uz]=Shriftlar
+Name[uz@cyrillic]=Шрифтлар
+Name[ven]=Fontu
+Name[vi]=Phông chữ
+Name[wa]=Fontes
+Name[xh]=Uhlobo lwamagama
+Name[zh_CN]=字体
+Name[zh_TW]=字型
+Name[zu]=Izinhlobo zamagama
+Open=false
+X-KDE-TreeModule=Directory
+X-KDE-KonqSidebarModule=konqsidebar_tree
diff --git a/kcontrol/kfontinst/kio/fonts.protocol b/kcontrol/kfontinst/kio/fonts.protocol
new file mode 100644
index 000000000..7f54dd0cc
--- /dev/null
+++ b/kcontrol/kfontinst/kio/fonts.protocol
@@ -0,0 +1,18 @@
+[Protocol]
+exec=kio_fonts
+protocol=fonts
+input=none
+output=filesystem
+listing=Name,Type,Size,Date,AccessDate,Access,Owner,Group,Link
+reading=true
+writing=true
+makedir=false
+deleting=true
+moving=true
+linking=false
+copyToFile=false
+copyFromFile=true
+Icon=fonts
+defaultMimetype=application/octet-stream
+maxInstances=1
+Class=:local
diff --git a/kcontrol/kfontinst/kio/package.desktop b/kcontrol/kfontinst/kio/package.desktop
new file mode 100644
index 000000000..4ee3543de
--- /dev/null
+++ b/kcontrol/kfontinst/kio/package.desktop
@@ -0,0 +1,74 @@
+[Desktop Entry]
+Type=MimeType
+MimeType=fonts/package
+Icon=font
+Patterns=*.fonts.tar.gz
+Comment=Fonts Package
+Comment[af]=Skriftipes Paket
+Comment[ar]=حزمة المحارف
+Comment[be]=Пакет шрыфтоў
+Comment[bg]=Пакет с шрифтове
+Comment[bn]=ফন্ট প্যাকেজ
+Comment[bs]=Paket fontova
+Comment[ca]=Paquet de lletres
+Comment[cs]=Balík písem
+Comment[csb]=Paczét fòntów
+Comment[da]=Skrifttypepakke
+Comment[de]=Schriftartenpaket
+Comment[el]=Πακέτο γραμματοσειρών
+Comment[eo]=Tiparpakaĵo
+Comment[es]=Paquete de tipos de letra
+Comment[et]=Fondipakett
+Comment[eu]=Letra-tipoen paketea
+Comment[fa]=بستۀ قلمها
+Comment[fi]=Kirjasinpaketti
+Comment[fr]=Paquet de polices
+Comment[fy]=Lettertypenpakket
+Comment[ga]=Pacáiste na gClónna
+Comment[gl]=Pacote das Fontes
+Comment[he]=חבילת גופנים
+Comment[hr]=Paket fontova
+Comment[hu]=Betűtípuscsomag
+Comment[id]=Paket Font
+Comment[is]=Leturpakki
+Comment[it]=Pacchetto tipi di caratteri
+Comment[ja]=フォントパッケージ
+Comment[ka]=შრიფტების პაკეტი
+Comment[kk]=Қаріп дестесі
+Comment[km]=កញ្ចប់​ពុម្ពអក្សរ
+Comment[lt]=Šriftų paketas
+Comment[mk]=Пакет со фонтови
+Comment[ms]=Pakej Fon
+Comment[nb]=Pakke for skrifttyper
+Comment[nds]=Schriftoorden-Paket
+Comment[ne]=फन्ट प्याकेज
+Comment[nl]=Lettertypenpakket
+Comment[nn]=Pakke for skrifter
+Comment[pa]=ਫੋਂਟ ਪੈਕੇਜ
+Comment[pl]=Pakiet czcionek
+Comment[pt]=Pacote de Tipos de Letra
+Comment[pt_BR]=Pacote de Fontes
+Comment[ro]=Pachet de fonturi
+Comment[ru]=Пакет шрифтов
+Comment[rw]=Rukomatanya y'Imyandikire
+Comment[se]=Fontapáhkka
+Comment[sk]=Balík písiem
+Comment[sl]=Paket pisav
+Comment[sr]=Пакет фонтова
+Comment[sr@Latn]=Paket fontova
+Comment[sv]=Teckensnittspaket
+Comment[tg]=Бастаи ҳарфҳо
+Comment[th]=แพคเกจแบบอักษร
+Comment[tr]=Yazıtipi Paketi
+Comment[tt]=Yazular Tuplaması
+Comment[uk]=Пакунок шрифтів
+Comment[uz]=Shrift
+Comment[uz@cyrillic]=Шрифт
+Comment[vi]=Gói Phông chữ
+Comment[wa]=Paket di fontes
+Comment[zh_CN]=字体包
+Comment[zh_TW]=字型套件
+
+[Property::X-KDE-LocalProtocol]
+Type=QString
+Value=tar
diff --git a/kcontrol/kfontinst/kio/system-folder.desktop b/kcontrol/kfontinst/kio/system-folder.desktop
new file mode 100644
index 000000000..07bf9d703
--- /dev/null
+++ b/kcontrol/kfontinst/kio/system-folder.desktop
@@ -0,0 +1,79 @@
+[Desktop Entry]
+Comment=System Fonts Folder
+Comment[af]=Stelsel Skrif tipe Gids
+Comment[ar]=مجلد محارف النظام
+Comment[be]=Тэчка сістэмных шрыфтоў
+Comment[bg]=Директория за системните шрифтове
+Comment[bn]=সিস্টেম ফন্ট ফোল্ডার
+Comment[br]=Renkell fontoù ar reizhiad
+Comment[bs]=Sistemski direktorij sa fontovima
+Comment[ca]=Carpeta de lletres del sistema
+Comment[cs]=Složka se systémovými písmy
+Comment[csb]=Katalog systemòwëch fòntów
+Comment[da]=Mappe til systemets skrifttyper
+Comment[de]=Ordner für Systemschriften
+Comment[el]=Φάκελος γραμματοσειρών συστήματος
+Comment[eo]=Sistema tipardosierujo
+Comment[es]=Carpeta de tipos de letra del sistema
+Comment[et]=Süsteemi fontide kataloog
+Comment[eu]=Sistemaren letra-tipoen karpeta
+Comment[fa]=پوشۀ قلمهای سیستم
+Comment[fi]=Järjestelmän kirjasinkansio
+Comment[fr]=Dossier système de polices de caractères
+Comment[fy]=Systeemlettertypenmap
+Comment[ga]=Fillteán Clónna an Chórais
+Comment[gl]=Cartafol das Fontes do Sistema
+Comment[he]=תיקיית גופני מערכת
+Comment[hi]=तंत्र फ़ॉन्ट्स फ़ोल्डर
+Comment[hr]=Mapa sistemskih fontova
+Comment[hu]=A rendszer betűtípusainak könyvtára
+Comment[id]=Folder Font Sistem
+Comment[is]=Kerfisleturmappa
+Comment[it]=Cartella dei caratteri di sistema
+Comment[ja]=システムフォントフォルダ
+Comment[ka]=სისტემური ფონტების საქაღალდე
+Comment[kk]=Жүйелік қаріптер қапшығы
+Comment[km]=ថត​ពុម្ពអក្សរ​ប្រព័ន្ធ
+Comment[lt]=Sistemos šriftų aplankas
+Comment[lv]=Sistēmas fontu mape
+Comment[mk]=Папка со системски фонтови
+Comment[ms]=Folder Fon Sistem
+Comment[mt]=Direttorju tal-fonts tas-sistema
+Comment[nb]=Mappe for systemskrifttyper
+Comment[nds]=Orner för de Systeemschriftoorden
+Comment[ne]=फन्ट फोल्डर प्रणाली
+Comment[nl]=Systeemlettertypenmap
+Comment[nn]=Systemskriftmappe
+Comment[pa]=ਸਿਸਟਮ ਫੋਂਟ ਫੋਲਡਰ
+Comment[pl]=Katalog czcionek systemowych
+Comment[pt]=Pasta de Tipos de Letra do Sistema
+Comment[pt_BR]=Pasta de Fontes do Sistema
+Comment[ro]=Folder fonturi de sistem
+Comment[ru]=Папка системных шрифтов
+Comment[rw]=Ububiko bw'Imyandikire Sisitemu
+Comment[se]=Vuogádatfontamáhppa
+Comment[sk]=Priečinok systémových písiem
+Comment[sl]=Mapa za sistemske pisave
+Comment[sr]=Фасцикла за системске фонтове
+Comment[sr@Latn]=Fascikla za sistemske fontove
+Comment[sv]=Systemteckensnittskatalog
+Comment[ta]=அமைப்பு எழுத்துருக்கள் அடைவு
+Comment[tg]=Системаи феҳристи ҳарфҳо
+Comment[th]=โฟลเดอร์แฟ้มแบบอักษรของระบบ
+Comment[tr]=Sistem Yazı Tipi Klasörü
+Comment[tt]=Sistem Yazular Törgäge
+Comment[uk]=Тека системних шрифтів
+Comment[uz]=Tizim shriftlarining jildi
+Comment[uz@cyrillic]=Тизим шрифтларининг жилди
+Comment[vi]=Thư mục Phông chữ Hệ thống
+Comment[wa]=Ridant di fontes do sistinme
+Comment[zh_CN]=系统字体文件夹
+Comment[zh_TW]=系統字型資料夾
+Icon=folder_red
+Type=MimeType
+MimeType=fonts/system-folder
+Patterns=
+
+X-KDE-AutoEmbed=true
+X-KDE-IsAlso=inode/directory
+
diff --git a/kcontrol/kfontinst/lib/FcEngine.cpp b/kcontrol/kfontinst/lib/FcEngine.cpp
new file mode 100644
index 000000000..0b3e51767
--- /dev/null
+++ b/kcontrol/kfontinst/lib/FcEngine.cpp
@@ -0,0 +1,1179 @@
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qfontmetrics.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <kurl.h>
+#include <kconfig.h>
+#include <kglobalsettings.h>
+#include <kio/netaccess.h>
+#include <math.h>
+#include "FcEngine.h"
+#include "KfiConstants.h"
+#ifdef HAVE_XFT
+#include <X11/Xlib.h>
+#include <X11/Xft/Xft.h>
+#include <fixx11h.h>
+#endif
+
+#define KFI_HAVE_OBLIQUE // Do we differentiate between Italic and Oblique?
+#define KFI_HAVE_MEDIUM_WEIGHT // Do we differentiate between Medium and Normal weights?
+
+#define KFI_PREVIEW_GROUP "Preview Settings"
+#define KFI_PREVIEW_STRING_KEY "String"
+
+#ifdef HAVE_XFT
+#define KFI_DISPLAY(pix) (pix ? pix->x11Display() : QPaintDevice::x11AppDisplay())
+#endif
+
+namespace KFI
+{
+
+const int CFcEngine::constScalableSizes[]={8, 10, 12, 24, 36, 48, 64, 72, 96, 0 };
+const int CFcEngine::constDefaultAlphaSize=24;
+
+static int fcWeight(int weight)
+{
+ if(weight<FC_WEIGHT_ULTRALIGHT)
+ return FC_WEIGHT_THIN;
+
+ if(weight<(FC_WEIGHT_ULTRALIGHT+FC_WEIGHT_LIGHT)/2)
+ return FC_WEIGHT_ULTRALIGHT;
+
+ if(weight<(FC_WEIGHT_LIGHT+FC_WEIGHT_NORMAL)/2)
+ return FC_WEIGHT_LIGHT;
+
+#ifdef KFI_HAVE_MEDIUM_WEIGHT
+ if(weight<(FC_WEIGHT_NORMAL+FC_WEIGHT_MEDIUM)/2)
+ return FC_WEIGHT_NORMAL;
+
+ if(weight<(FC_WEIGHT_MEDIUM+FC_WEIGHT_SEMIBOLD)/2)
+ return FC_WEIGHT_MEDIUM;
+#else
+ if(weight<(FC_WEIGHT_NORMAL+FC_WEIGHT_SEMIBOLD)/2)
+ return FC_WEIGHT_NORMAL;
+#endif
+
+ if(weight<(FC_WEIGHT_SEMIBOLD+FC_WEIGHT_BOLD)/2)
+ return FC_WEIGHT_SEMIBOLD;
+
+ if(weight<(FC_WEIGHT_BOLD+FC_WEIGHT_ULTRABOLD)/2)
+ return FC_WEIGHT_BOLD;
+
+ if(weight<(FC_WEIGHT_ULTRABOLD+FC_WEIGHT_HEAVY)/2)
+ return FC_WEIGHT_ULTRABOLD;
+
+ return FC_WEIGHT_HEAVY;
+}
+
+static int fcToQtWeight(int weight)
+{
+ switch(weight)
+ {
+ case FC_WEIGHT_THIN:
+ return 0;
+ case FC_WEIGHT_ULTRALIGHT:
+ return QFont::Light>>1;
+ case FC_WEIGHT_LIGHT:
+ return QFont::Light;
+ default:
+ case FC_WEIGHT_NORMAL:
+ return QFont::Normal;
+ case FC_WEIGHT_MEDIUM:
+#ifdef KFI_HAVE_MEDIUM_WEIGHT
+ return (QFont::Normal+QFont::DemiBold)>>1;
+#endif
+ return QFont::Normal;
+ case FC_WEIGHT_SEMIBOLD:
+ return QFont::DemiBold;
+ case FC_WEIGHT_BOLD:
+ return QFont::Bold;
+ case FC_WEIGHT_ULTRABOLD:
+ return (QFont::Bold+QFont::Black)>>1;
+ case FC_WEIGHT_HEAVY:
+ return QFont::Black;
+ }
+}
+
+#ifndef KFI_FC_NO_WIDTHS
+static int fcWidth(int width)
+{
+ if(width<FC_WIDTH_EXTRACONDENSED)
+ return FC_WIDTH_ULTRACONDENSED;
+
+ if(width<(FC_WIDTH_EXTRACONDENSED+FC_WIDTH_CONDENSED)/2)
+ return FC_WIDTH_EXTRACONDENSED;
+
+ if(width<(FC_WIDTH_CONDENSED+FC_WIDTH_SEMICONDENSED)/2)
+ return FC_WIDTH_CONDENSED;
+
+ if(width<(FC_WIDTH_SEMICONDENSED+FC_WIDTH_NORMAL)/2)
+ return FC_WIDTH_SEMICONDENSED;
+
+ if(width<(FC_WIDTH_NORMAL+FC_WIDTH_SEMIEXPANDED)/2)
+ return FC_WIDTH_NORMAL;
+
+ if(width<(FC_WIDTH_SEMIEXPANDED+FC_WIDTH_EXPANDED)/2)
+ return FC_WIDTH_SEMIEXPANDED;
+
+ if(width<(FC_WIDTH_EXPANDED+FC_WIDTH_EXTRAEXPANDED)/2)
+ return FC_WIDTH_EXPANDED;
+
+ if(width<(FC_WIDTH_EXTRAEXPANDED+FC_WIDTH_ULTRAEXPANDED)/2)
+ return FC_WIDTH_EXTRAEXPANDED;
+
+ return FC_WIDTH_ULTRAEXPANDED;
+}
+
+static int fcToQtWidth(int weight)
+{
+ switch(weight)
+ {
+ case FC_WIDTH_ULTRACONDENSED:
+ return QFont::UltraCondensed;
+ case FC_WIDTH_EXTRACONDENSED:
+ return QFont::ExtraCondensed;
+ case FC_WIDTH_CONDENSED:
+ return QFont::Condensed;
+ case FC_WIDTH_SEMICONDENSED:
+ return QFont::SemiCondensed;
+ default:
+ case FC_WIDTH_NORMAL:
+ return QFont::Unstretched;
+ case FC_WIDTH_SEMIEXPANDED:
+ return QFont::SemiExpanded;
+ case FC_WIDTH_EXPANDED:
+ return QFont::Expanded;
+ case FC_WIDTH_EXTRAEXPANDED:
+ return QFont::ExtraExpanded;
+ case FC_WIDTH_ULTRAEXPANDED:
+ return QFont::UltraExpanded;
+ }
+}
+#endif
+
+static int fcSlant(int slant)
+{
+ if(slant<FC_SLANT_ITALIC)
+ return FC_SLANT_ROMAN;
+
+#ifdef KFI_HAVE_OBLIQUE
+ if(slant<(FC_SLANT_ITALIC+FC_SLANT_OBLIQUE)/2)
+ return FC_SLANT_ITALIC;
+
+ return FC_SLANT_OBLIQUE;
+#else
+ return FC_SLANT_ITALIC;
+#endif
+}
+
+static bool fcToQtSlant(int slant)
+{
+ return FC_SLANT_ROMAN==slant ? false : true;
+}
+
+static int fcSpacing(int spacing)
+{
+ if(spacing<FC_MONO)
+ return FC_PROPORTIONAL;
+
+ if(spacing<(FC_MONO+FC_CHARCELL)/2)
+ return FC_MONO;
+
+ return FC_CHARCELL;
+}
+
+static int strToWeight(const QString &str, QString &newStr)
+{
+ if(0==str.find(i18n(KFI_WEIGHT_THIN), 0, false))
+ {
+ newStr=str.mid(i18n(KFI_WEIGHT_THIN).length());
+ return FC_WEIGHT_THIN;
+ }
+ if(0==str.find(i18n(KFI_WEIGHT_EXTRALIGHT), 0, false))
+ {
+ newStr=str.mid(i18n(KFI_WEIGHT_EXTRALIGHT).length());
+ return FC_WEIGHT_EXTRALIGHT;
+ }
+ if(0==str.find(i18n(KFI_WEIGHT_ULTRALIGHT), 0, false))
+ {
+ newStr=str.mid(i18n(KFI_WEIGHT_ULTRALIGHT).length());
+ return FC_WEIGHT_ULTRALIGHT;
+ }
+ if(0==str.find(i18n(KFI_WEIGHT_LIGHT), 0, false))
+ {
+ newStr=str.mid(i18n(KFI_WEIGHT_LIGHT).length());
+ return FC_WEIGHT_LIGHT;
+ }
+ if(0==str.find(i18n(KFI_WEIGHT_REGULAR), 0, false))
+ {
+ newStr=str.mid(i18n(KFI_WEIGHT_REGULAR).length());
+ return FC_WEIGHT_REGULAR;
+ }
+ if(0==str.find(i18n(KFI_WEIGHT_NORMAL), 0, false))
+ {
+ newStr=str.mid(i18n(KFI_WEIGHT_NORMAL).length());
+ return FC_WEIGHT_NORMAL;
+ }
+ if(0==str.find(i18n(KFI_WEIGHT_MEDIUM), 0, false))
+ {
+ newStr=str.mid(i18n(KFI_WEIGHT_MEDIUM).length());
+ return FC_WEIGHT_MEDIUM;
+ }
+ if(0==str.find(i18n(KFI_WEIGHT_DEMIBOLD), 0, false))
+ {
+ newStr=str.mid(i18n(KFI_WEIGHT_DEMIBOLD).length());
+ return FC_WEIGHT_SEMIBOLD;
+ }
+ if(0==str.find(i18n(KFI_WEIGHT_SEMIBOLD), 0, false))
+ {
+ newStr=str.mid(i18n(KFI_WEIGHT_SEMIBOLD).length());
+ return FC_WEIGHT_SEMIBOLD;
+ }
+ if(0==str.find(i18n(KFI_WEIGHT_BOLD), 0, false))
+ {
+ newStr=str.mid(i18n(KFI_WEIGHT_BOLD).length());
+ return FC_WEIGHT_BOLD;
+ }
+ if(0==str.find(i18n(KFI_WEIGHT_EXTRABOLD), 0, false))
+ {
+ newStr=str.mid(i18n(KFI_WEIGHT_EXTRABOLD).length());
+ return FC_WEIGHT_EXTRABOLD;
+ }
+ if(0==str.find(i18n(KFI_WEIGHT_ULTRABOLD), 0, false))
+ {
+ newStr=str.mid(i18n(KFI_WEIGHT_ULTRABOLD).length());
+ return FC_WEIGHT_ULTRABOLD;
+ }
+ if(0==str.find(i18n(KFI_WEIGHT_BLACK), 0, false))
+ {
+ newStr=str.mid(i18n(KFI_WEIGHT_BLACK).length());
+ return FC_WEIGHT_BLACK;
+ }
+ if(0==str.find(i18n(KFI_WEIGHT_HEAVY), 0, false))
+ {
+ newStr=str.mid(i18n(KFI_WEIGHT_HEAVY).length());
+ return FC_WEIGHT_HEAVY;
+ }
+
+ newStr=str;
+ return FC_WEIGHT_REGULAR;
+}
+
+#ifndef KFI_FC_NO_WIDTHS
+static int strToWidth(const QString &str, QString &newStr)
+{
+ if(0==str.find(i18n(KFI_WIDTH_ULTRACONDENSED), 0, false))
+ {
+ newStr=str.mid(i18n(KFI_WIDTH_ULTRACONDENSED).length());
+ return FC_WIDTH_ULTRACONDENSED;
+ }
+ if(0==str.find(i18n(KFI_WIDTH_EXTRACONDENSED), 0, false))
+ {
+ newStr=str.mid(i18n(KFI_WIDTH_EXTRACONDENSED).length());
+ return FC_WIDTH_EXTRACONDENSED;
+ }
+ if(0==str.find(i18n(KFI_WIDTH_CONDENSED), 0, false))
+ {
+ newStr=str.mid(i18n(KFI_WIDTH_CONDENSED).length());
+ return FC_WIDTH_CONDENSED;
+ }
+ if(0==str.find(i18n(KFI_WIDTH_SEMICONDENSED), 0, false))
+ {
+ newStr=str.mid(i18n(KFI_WIDTH_SEMICONDENSED).length());
+ return FC_WIDTH_SEMICONDENSED;
+ }
+ if(0==str.find(i18n(KFI_WIDTH_NORMAL), 0, false))
+ {
+ newStr=str.mid(i18n(KFI_WIDTH_NORMAL).length());
+ return FC_WIDTH_NORMAL;
+ }
+ if(0==str.find(i18n(KFI_WIDTH_SEMIEXPANDED), 0, false))
+ {
+ newStr=str.mid(i18n(KFI_WIDTH_SEMIEXPANDED).length());
+ return FC_WIDTH_SEMIEXPANDED;
+ }
+ if(0==str.find(i18n(KFI_WIDTH_EXPANDED), 0, false))
+ {
+ newStr=str.mid(i18n(KFI_WIDTH_EXPANDED).length());
+ return FC_WIDTH_EXPANDED;
+ }
+ if(0==str.find(i18n(KFI_WIDTH_EXTRAEXPANDED), 0, false))
+ {
+ newStr=str.mid(i18n(KFI_WIDTH_EXTRAEXPANDED).length());
+ return FC_WIDTH_EXTRAEXPANDED;
+ }
+ if(0==str.find(i18n(KFI_WIDTH_ULTRAEXPANDED), 0, false))
+ {
+ newStr=str.mid(i18n(KFI_WIDTH_ULTRAEXPANDED).length());
+ return FC_WIDTH_ULTRAEXPANDED;
+ }
+
+ newStr=str;
+ return FC_WIDTH_NORMAL;
+}
+#endif
+
+static int strToSlant(const QString &str)
+{
+ if(-1!=str.find(i18n(KFI_SLANT_ITALIC)))
+ return FC_SLANT_ITALIC;
+ if(-1!=str.find(i18n(KFI_SLANT_OBLIQUE)))
+ return FC_SLANT_OBLIQUE;
+ return FC_SLANT_ROMAN;
+}
+
+static void drawText(QPainter &painter, int x, int y, int width, const QString &str)
+{
+ QString s(str);
+ bool addedElipses=false;
+
+ width-=x*2;
+ while(s.length()>3 && painter.fontMetrics().size(0, s).width()>width)
+ {
+ if(!addedElipses)
+ {
+ s.remove(s.length()-2, 2);
+ s.append("...");
+ addedElipses=true;
+ }
+ else
+ s.remove(s.length()-4, 1);
+ }
+ painter.drawText(x, y, s);
+}
+
+inline bool equal(double d1, double d2)
+{
+ return (fabs(d1 - d2) < 0.0001);
+}
+
+inline bool equalWeight(int a, int b)
+{
+ return a==b || fcWeight(a)==fcWeight(b);
+}
+
+#ifndef KFI_FC_NO_WIDTHS
+inline bool equalWidth(int a, int b)
+{
+ return a==b || fcWidth(a)==fcWidth(b);
+}
+#endif
+
+inline bool equalSlant(int a, int b)
+{
+ return a==b || fcSlant(a)==fcSlant(b);
+}
+
+#ifdef HAVE_XFT
+static bool drawChar(QPixmap &pix, XftDraw *xftDraw, XftFont *xftFont, XftColor *xftCol, const QString &text, int pos,
+ int &x, int &y, int w, int h, int fSize, int offset)
+{
+ XGlyphInfo extents;
+ const FcChar16 *str=(FcChar16 *)(&(text.ucs2()[pos]));
+
+ XftTextExtents16(pix.x11Display(), xftFont, str, 1, &extents);
+
+ if(x+extents.width+2>w)
+ {
+ x=offset;
+ y+=fSize;
+ }
+
+ if(y+offset<h)
+ {
+ XftDrawString16(xftDraw, xftCol, xftFont, x, y, str, 1);
+ x+=extents.width+2;
+ return true;
+ }
+ return false;
+}
+
+static bool drawString(QPixmap &pix, XftDraw *xftDraw, XftFont *xftFont, XftColor *xftCol, const QString &text,
+ int x, int &y, int h, int offset)
+{
+ XGlyphInfo extents;
+ const FcChar16 *str=(FcChar16 *)(text.ucs2());
+
+ XftTextExtents16(pix.x11Display(), xftFont, str, text.length(), &extents);
+ if(y+extents.height<h)
+ XftDrawString16(xftDraw, xftCol, xftFont, x, y+extents.y, str, text.length());
+ if(extents.height>0)
+ {
+ y+=extents.height+offset;
+ return true;
+ }
+ return false;
+}
+
+static bool drawGlyph(QPixmap &pix, XftDraw *xftDraw, XftFont *xftFont, XftColor *xftCol, FT_UInt i,
+ int &x, int &y, int &w, int &h, int fSize, int offset)
+{
+ XGlyphInfo extents;
+
+ XftGlyphExtents(pix.x11Display(), xftFont, &i, 1, &extents);
+
+ if(x+extents.width+2>w)
+ {
+ x=offset;
+ y+=fSize;
+ }
+
+ if(y+offset<h)
+ {
+ XftDrawGlyphs(xftDraw, xftCol, xftFont, x, y, &i, 1);
+ x+=extents.width+2;
+ return true;
+ }
+ return false;
+}
+
+inline int point2Pixel(int point)
+{
+ return (point*QPaintDevice::x11AppDpiX()+36)/72;
+}
+
+static bool hasStr(XftFont *font, QString &str)
+{
+ unsigned int slen=str.length(),
+ ch;
+
+ for(ch=0; ch<slen; ++ch)
+ if(!FcCharSetHasChar(font->charset, str[ch].unicode()))
+ return false;
+ return true;
+}
+#endif
+
+CFcEngine::CFcEngine()
+ : itsIndex(-1),
+ itsIndexCount(1)
+{
+}
+
+CFcEngine::~CFcEngine()
+{
+ // Clear any fonts that may have been added...
+ FcConfigAppFontClear(FcConfigGetCurrent());
+}
+
+QString CFcEngine::getName(const KURL &url, int faceNo)
+{
+ if(url!=itsLastUrl || faceNo!=itsIndex)
+ parseUrl(url, faceNo);
+
+ return itsDescriptiveName;
+}
+
+#ifdef HAVE_XFT
+bool CFcEngine::draw(const KURL &url, int w, int h, QPixmap &pix, int faceNo, bool thumb)
+{
+ bool rv=false;
+
+ if((url==itsLastUrl && faceNo==itsIndex) || parseUrl(url, faceNo))
+ {
+ rv=true;
+
+ if(!itsInstalled) // Then add to fontconfig's list, so that Xft can display it...
+ {
+ FcInitReinitialize();
+ FcConfigAppFontAddFile(FcConfigGetCurrent(), (const FcChar8 *)(itsName.utf8().data()));
+ }
+
+ if(thumb && (w!=h || h>128))
+ thumb=false;
+
+ int offset=thumb
+ ? h<=32
+ ? 2
+ : 3
+ : 4,
+ x=offset, y=offset;
+
+ pix.resize(w, h);
+ pix.fill(Qt::white);
+
+ QPainter painter(&pix);
+
+ getSizes(&pix);
+
+ if(itsSizes.size())
+ {
+ XRenderColor xrenderCol;
+ XftColor xftCol;
+
+ xrenderCol.red=xrenderCol.green=xrenderCol.blue=0;
+ xrenderCol.alpha=0xffff;
+ XftColorAllocValue(pix.x11Display(), DefaultVisual(pix.x11Display(),
+ pix.x11Screen()),
+ DefaultColormap(pix.x11Display(), pix.x11Screen()),
+ &xrenderCol, &xftCol);
+
+ XftDraw *xftDraw=XftDrawCreate(pix.x11Display(), (Pixmap)(pix.handle()),
+ (Visual*)(pix.x11Visual()), pix.x11Colormap());
+
+ if(xftDraw)
+ {
+ XftFont *xftFont=NULL;
+ bool drawGlyphs=false;
+
+ if(thumb)
+ {
+ QString text(i18n("AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789"));
+
+ //
+ // Calculate size of text...
+ int fSize= h <= 32
+ ? h-(offset*2) // 1 line of chars...
+ : h <= 64
+ ? (h-(offset*3))/2 // 2 lines...
+ : (h-(offset*4))/3; // 3 lines or more
+
+ if(!itsScalable) // Then need to get nearest size...
+ {
+ int bSize=fSize;
+
+ for(unsigned int s=0; s<itsSizes.size(); ++s)
+ if (itsSizes[s]<=fSize)
+ bSize=itsSizes[s];
+ fSize=bSize;
+ }
+
+ unsigned int ch;
+
+ xftFont=getFont(fSize, &pix);
+
+ y=fSize;
+ if(xftFont)
+ {
+ drawGlyphs=!hasStr(xftFont, text);
+
+ if(!drawGlyphs)
+ for(ch=0; ch<text.length(); ++ch) // Display char by char so that it wraps...
+ if(!drawChar(pix, xftDraw, xftFont, &xftCol, text, ch, x, y, w, h, fSize, offset))
+ break;
+ if(drawGlyphs)
+ {
+ FT_Face face=XftLockFace(xftFont);
+
+ if(face)
+ {
+ for(int i=1; i<face->num_glyphs && y<w; ++i) // Glyph 0 is the NULL glyph
+ if(!drawGlyph(pix, xftDraw, xftFont, &xftCol, i, x, y, w, h, fSize, offset))
+ break;
+
+ XftUnlockFace(xftFont);
+ }
+ }
+ }
+ }
+ else
+ {
+ QString lowercase(getLowercaseLetters()),
+ uppercase(getUppercaseLetters()),
+ punctuation(getPunctuation()),
+ title(itsDescriptiveName.isEmpty()
+ ? i18n("ERROR: Could not determine font's name.")
+ : itsDescriptiveName);
+
+ if(1==itsSizes.size())
+ title=i18n("%1 [1 pixel]", "%1 [%n pixels]", itsSizes[0]).arg(title);
+
+ painter.setFont(KGlobalSettings::generalFont());
+ painter.setPen(Qt::black);
+ y=painter.fontMetrics().height();
+ drawText(painter, x, y, w-offset, title);
+ y+=4;
+ painter.drawLine(offset, y, w-(offset+1), y);
+ y+=8;
+
+ bool lc=true,
+ uc=true,
+ punc=true;
+
+ xftFont=getFont(itsAlphaSize, &pix);
+ if(xftFont)
+ {
+ lc=hasStr(xftFont, lowercase);
+ uc=hasStr(xftFont, uppercase);
+ punc=hasStr(xftFont, punctuation);
+
+ drawGlyphs=!lc && !uc;
+
+ if(!drawGlyphs)
+ {
+ if(lc)
+ drawString(pix, xftDraw, xftFont, &xftCol, lowercase, x, y, h, offset);
+ if(uc)
+ drawString(pix, xftDraw, xftFont, &xftCol, uppercase, x, y, h, offset);
+ if(punc)
+ drawString(pix, xftDraw, xftFont, &xftCol, punctuation, x, y, h, offset);
+ XftFontClose(pix.x11Display(), xftFont);
+ if(lc || uc || punc)
+ painter.drawLine(offset, y, w-(offset+1), y);
+ y+=8;
+ }
+
+ QString previewString(getPreviewString());
+ bool stop=false;
+
+ if(!drawGlyphs)
+ {
+ if(!lc && uc)
+ previewString=previewString.upper();
+ if(!uc && lc)
+ previewString=previewString.lower();
+ }
+
+ for(unsigned int s=0; s<itsSizes.size(); ++s)
+ {
+ xftFont=getFont(itsSizes[s], &pix);
+
+ if(xftFont)
+ {
+ if(drawGlyphs)
+ {
+ FT_Face face=XftLockFace(xftFont);
+
+ if(face)
+ {
+ int space=itsSizes[s]/10;
+ XGlyphInfo extents;
+
+ if(!space)
+ space=1;
+
+ for(int i=1; i<face->num_glyphs && y<w && !stop; ++i)
+ {
+ XftGlyphExtents(pix.x11Display(), xftFont, (const FT_UInt *)&i, 1, &extents);
+
+ if(y+extents.height>h)
+ stop=true;
+ else
+ {
+ if(x+extents.width<w)
+ XftDrawGlyphs(xftDraw, &xftCol, xftFont, x, y+extents.y,
+ (const FT_UInt *)&i, 1);
+ if(extents.width>0)
+ x+=extents.width+space;
+ }
+ if(x>=w || i==face->num_glyphs-1)
+ {
+ y+=itsSizes[s]+offset;
+ x=offset;
+ break;
+ }
+ }
+
+ XftUnlockFace(xftFont);
+ }
+ }
+ else
+ drawString(pix, xftDraw, xftFont, &xftCol, previewString, x, y, h, offset);
+ XftFontClose(pix.x11Display(), xftFont);
+ }
+ }
+ }
+ }
+
+ XftDrawDestroy(xftDraw);
+ }
+ }
+ }
+
+ return rv;
+}
+#endif
+
+QString CFcEngine::getPreviewString()
+{
+ KConfig cfg(KFI_UI_CFG_FILE);
+
+ cfg.setGroup(KFI_PREVIEW_GROUP);
+
+ QString str(cfg.readEntry(KFI_PREVIEW_STRING_KEY));
+
+ return str.isEmpty() ? i18n("A sentence that uses all of the letters of the alphabet",
+ "The quick brown fox jumps over the lazy dog")
+ : str;
+}
+
+void CFcEngine::setPreviewString(const QString &str)
+{
+ KConfig cfg(KFI_UI_CFG_FILE);
+
+ cfg.setGroup(KFI_PREVIEW_GROUP);
+ cfg.writeEntry(KFI_PREVIEW_STRING_KEY, str);
+}
+
+QString CFcEngine::getUppercaseLetters()
+{
+ return i18n("All of the letters of the alphabet, uppercase", "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+}
+
+QString CFcEngine::getLowercaseLetters()
+{
+ return i18n("All of the letters of the alphabet, lowercase", "abcdefghijklmnopqrstuvwxyz");
+}
+
+QString CFcEngine::getPunctuation()
+{
+ return i18n("Numbers and characters", "0123456789.:,;(*!?'/\\\")£$€%^&-+@~#<>{}[]");
+}
+
+QString CFcEngine::getFcString(FcPattern *pat, const char *val, int faceNo)
+{
+ QString rv;
+ FcChar8 *fcStr;
+
+ if(FcResultMatch==FcPatternGetString(pat, val, faceNo, &fcStr))
+ rv=QString::fromUtf8((char *)fcStr);
+
+ return rv;
+}
+
+QString CFcEngine::createName(FcPattern *pat, int faceNo)
+{
+//CPD: TODO: the names *need* to match up with kfontchooser's...
+ QString name(getFcString(pat, FC_FAMILY, faceNo)),
+ str;
+ int intVal;
+ bool comma=false;
+
+ if (FcResultMatch==FcPatternGetInteger(pat, FC_WEIGHT, faceNo, &intVal))
+ {
+ str=weightStr(intVal);
+ if(!str.isEmpty())
+ {
+ name+=QString(", ")+str;
+ comma=true;
+ }
+ }
+
+ if (FcResultMatch==FcPatternGetInteger(pat, FC_SLANT, faceNo, &intVal))
+ {
+ str=slantStr(intVal);
+ if(!str.isEmpty())
+ {
+ if(!comma)
+ {
+ name+=QChar(',');
+ comma=true;
+ }
+ name+=QChar(' ')+str;
+ }
+ }
+
+#ifndef KFI_FC_NO_WIDTHS
+ if (FcResultMatch==FcPatternGetInteger(pat, FC_WIDTH, faceNo, &intVal))
+ {
+ str=widthStr(intVal);
+ if(!str.isEmpty())
+ name+=QChar(' ')+str;
+ }
+#endif
+
+ return name;
+}
+
+QString CFcEngine::weightStr(int weight, bool emptyNormal)
+{
+ switch(fcWeight(weight))
+ {
+ case FC_WEIGHT_THIN:
+ return i18n(KFI_WEIGHT_THIN);
+ case FC_WEIGHT_ULTRALIGHT:
+ return i18n(KFI_WEIGHT_ULTRALIGHT);
+ case FC_WEIGHT_LIGHT:
+ return i18n(KFI_WEIGHT_LIGHT);
+ case FC_WEIGHT_NORMAL:
+ return emptyNormal ? QString::null : i18n(KFI_WEIGHT_NORMAL);
+ case FC_WEIGHT_MEDIUM:
+ return i18n(KFI_WEIGHT_MEDIUM);
+ case FC_WEIGHT_DEMIBOLD:
+ return i18n(KFI_WEIGHT_SEMIBOLD);
+ case FC_WEIGHT_BOLD:
+ return i18n(KFI_WEIGHT_BOLD);
+ case FC_WEIGHT_ULTRABOLD:
+ return i18n(KFI_WEIGHT_ULTRABOLD);
+ default:
+ return i18n(KFI_WEIGHT_HEAVY);
+ }
+}
+
+#ifndef KFI_FC_NO_WIDTHS
+QString CFcEngine::widthStr(int width, bool emptyNormal)
+{
+ switch(fcWidth(width))
+ {
+ case FC_WIDTH_ULTRACONDENSED:
+ return i18n(KFI_WIDTH_ULTRACONDENSED);
+ case FC_WIDTH_EXTRACONDENSED:
+ return i18n(KFI_WIDTH_EXTRACONDENSED);
+ case FC_WIDTH_CONDENSED:
+ return i18n(KFI_WIDTH_CONDENSED);
+ case FC_WIDTH_SEMICONDENSED:
+ return i18n(KFI_WIDTH_SEMICONDENSED);
+ case FC_WIDTH_NORMAL:
+ return emptyNormal ? QString::null : i18n(KFI_WIDTH_NORMAL);
+ case FC_WIDTH_SEMIEXPANDED:
+ return i18n(KFI_WIDTH_SEMIEXPANDED);
+ case FC_WIDTH_EXPANDED:
+ return i18n(KFI_WIDTH_EXPANDED);
+ case FC_WIDTH_EXTRAEXPANDED:
+ return i18n(KFI_WIDTH_EXTRAEXPANDED);
+ default:
+ return i18n(KFI_WIDTH_ULTRAEXPANDED);
+ }
+}
+#endif
+
+QString CFcEngine::slantStr(int slant, bool emptyNormal)
+{
+ switch(fcSlant(slant))
+ {
+ case FC_SLANT_OBLIQUE:
+ return i18n(KFI_SLANT_OBLIQUE);
+ case FC_SLANT_ITALIC:
+ return i18n(KFI_SLANT_ITALIC);
+ default:
+ return emptyNormal ? QString::null : i18n(KFI_SLANT_ROMAN);
+ }
+}
+
+QString CFcEngine::spacingStr(int spacing)
+{
+ switch(fcSpacing(spacing))
+ {
+ case FC_MONO:
+ return i18n(KFI_SPACING_MONO);
+ case FC_CHARCELL:
+ return i18n(KFI_SPACING_CHARCELL);
+ default:
+ return i18n(KFI_SPACING_PROPORTIONAL);
+ }
+}
+
+bool CFcEngine::getInfo(const KURL &url, int faceNo, QString &full, QString &family, QString &foundry, QString &weight,
+#ifndef KFI_FC_NO_WIDTHS
+ QString &width,
+#endif
+ QString &spacing, QString &slant)
+{
+ if(parseUrl(url, faceNo, true))
+ {
+ full=itsDescriptiveName;
+ if(url.isLocalFile())
+ {
+ int pos;
+
+ if(-1==(pos=itsDescriptiveName.find(", "))) // No style information...
+ family=itsDescriptiveName;
+ else
+ family=itsDescriptiveName.left(pos);
+ }
+ else
+ family=itsName;
+ weight=weightStr(itsWeight, false);
+#ifndef KFI_FC_NO_WIDTHS
+ width=widthStr(itsWidth, false);
+#endif
+ slant=slantStr(itsSlant, false);
+ spacing=spacingStr(itsSpacing);
+ foundry=itsFoundry;
+ return true;
+ }
+
+ return false;
+}
+
+QFont CFcEngine::getQFont(const QString &name, int size)
+{
+ parseName(name, 0, false);
+
+ QFont font(itsName, size, fcToQtWeight(itsWeight), fcToQtSlant(itsSlant));
+
+#ifndef KFI_FC_NO_WIDTHS
+ font.setStretch(fcToQtWidth(itsWidth));
+#endif
+ return font;
+}
+
+bool CFcEngine::parseUrl(const KURL &url, int faceNo, bool all)
+{
+ FcInitLoadConfigAndFonts();
+
+ // Possible urls:
+ //
+ // fonts:/times.ttf
+ // fonts:/System/times.ttf
+ // file:/home/wibble/hmm.ttf
+ //
+ if(KFI_KIO_FONTS_PROTOCOL==url.protocol())
+ {
+ KIO::UDSEntry udsEntry;
+ QString name;
+
+ FcInitReinitialize();
+ if(KIO::NetAccess::stat(url, udsEntry, NULL)) // Need to stat the url to get its font name...
+ {
+ KIO::UDSEntry::Iterator it(udsEntry.begin()),
+ end(udsEntry.end());
+
+ for( ; it != end; ++it)
+ if (KIO::UDS_NAME==(*it).m_uds)
+ {
+ name=(*it).m_str;
+ break;
+ }
+ }
+
+ if(!name.isEmpty())
+ {
+ parseName(name, faceNo, all);
+ itsInstalled=true;
+ }
+ else
+ return false;
+ }
+ else if(url.isLocalFile())
+ {
+ // Now lets see if its from the thumbnail job! if so, then file will just contain the URL!
+ QFile file(url.path());
+ bool isThumbnailUrl=false;
+
+ if(file.size()<2048 && file.open(IO_ReadOnly)) // Urls should be less than 2k, and fonts usually above!
+ {
+ QString thumbUrl;
+ QTextStream stream(&file);
+
+ thumbUrl=stream.readLine();
+ isThumbnailUrl=0==thumbUrl.find(KFI_KIO_FONTS_PROTOCOL) && parseUrl(KURL(thumbUrl), faceNo, all);
+ file.close();
+ }
+
+ if(!isThumbnailUrl) // Its not a thumbnail, so read the real font file...
+ {
+ itsName=url.path();
+
+ int count;
+ FcPattern *pat=FcFreeTypeQuery((const FcChar8 *)(QFile::encodeName(itsName).data()), 0, NULL, &count);
+
+ itsWeight=FC_WEIGHT_NORMAL;
+#ifndef KFI_FC_NO_WIDTHS
+ itsWidth=FC_WIDTH_NORMAL;
+#endif
+ itsSlant=FC_SLANT_ROMAN;
+ itsSpacing=FC_PROPORTIONAL;
+
+ if(pat)
+ {
+ itsDescriptiveName=createName(pat, faceNo);
+
+ if(all)
+ {
+ FcPatternGetInteger(pat, FC_WEIGHT, faceNo, &itsWeight);
+ FcPatternGetInteger(pat, FC_SLANT, faceNo, &itsSlant);
+#ifndef KFI_FC_NO_WIDTHS
+ FcPatternGetInteger(pat, FC_WIDTH, faceNo, &itsWidth);
+#endif
+ FcPatternGetInteger(pat, FC_SPACING, faceNo, &itsSpacing);
+ itsFoundry=getFcString(pat, FC_FOUNDRY, faceNo);
+ }
+
+ FcPatternDestroy(pat);
+ }
+ else
+ itsDescriptiveName=QString::null;
+
+ itsInstalled=false;
+ itsIndex=faceNo;
+ }
+ }
+ else
+ return false;
+
+ itsLastUrl=url;
+ return true;
+}
+
+void CFcEngine::parseName(const QString &name, int faceNo, bool all)
+{
+ int pos;
+
+ itsDescriptiveName=name;
+ itsSpacing=FC_PROPORTIONAL;
+ if(-1==(pos=name.find(", "))) // No style information...
+ {
+ itsWeight=FC_WEIGHT_NORMAL;
+#ifndef KFI_FC_NO_WIDTHS
+ itsWidth=FC_WIDTH_NORMAL;
+#endif
+ itsSlant=FC_SLANT_ROMAN;
+ itsName=name;
+ }
+ else
+ {
+ QString style(name.mid(pos+2));
+
+ itsWeight=strToWeight(style, style);
+#ifndef KFI_FC_NO_WIDTHS
+ itsWidth=strToWidth(style, style);
+#endif
+ itsSlant=strToSlant(style);
+ itsName=name.left(pos);
+ }
+
+ if(all)
+ {
+ FcObjectSet *os = FcObjectSetBuild(FC_SPACING, FC_FOUNDRY, (void *)0);
+ FcPattern *pat = FcPatternBuild(NULL,
+ FC_FAMILY, FcTypeString, (const FcChar8 *)(itsName.utf8().data()),
+ FC_WEIGHT, FcTypeInteger, itsWeight,
+ FC_SLANT, FcTypeInteger, itsSlant,
+#ifndef KFI_FC_NO_WIDTHS
+ FC_WIDTH, FcTypeInteger, itsWidth,
+#endif
+ NULL);
+ FcFontSet *set = FcFontList(0, pat, os);
+
+ FcPatternDestroy(pat);
+ FcObjectSetDestroy(os);
+
+ if(set && set->nfont)
+ {
+ FcPatternGetInteger(set->fonts[0], FC_SPACING, faceNo, &itsSpacing);
+ itsFoundry=getFcString(set->fonts[0], FC_FOUNDRY, faceNo);
+ }
+ }
+
+ itsIndex=0; // Doesn't matter, as we're gonna use font name!
+ itsLastUrl=KURL();
+}
+
+#ifdef HAVE_XFT
+XftFont * CFcEngine::getFont(int size, QPixmap *pix)
+{
+ if(itsInstalled)
+ return XftFontOpen(KFI_DISPLAY(pix), 0,
+ FC_FAMILY, FcTypeString, (const FcChar8 *)(itsName.utf8().data()),
+ FC_WEIGHT, FcTypeInteger, itsWeight,
+ FC_SLANT, FcTypeInteger, itsSlant,
+#ifndef KFI_FC_NO_WIDTHS
+ FC_WIDTH, FcTypeInteger, itsWidth,
+#endif
+ FC_PIXEL_SIZE, FcTypeDouble, (double)size,
+ NULL);
+ else
+ {
+ FcPattern *pattern = FcPatternBuild(NULL,
+ FC_FILE, FcTypeString, QFile::encodeName(itsName).data(),
+ FC_INDEX, FcTypeInteger, itsIndex,
+ FC_PIXEL_SIZE, FcTypeDouble, (double)size,
+ NULL);
+ return XftFontOpenPattern(KFI_DISPLAY(pix), pattern);
+ }
+}
+
+void CFcEngine::getSizes(QPixmap *pix)
+{
+ static const int constNumSizes=11;
+ static const int constNumSizeRanges=2;
+ static const int constSizes[constNumSizeRanges][constNumSizes]= { {8, 10, 12, 14, 16, 18, 24, 36, 48, 72, 96},
+ {7, 9, 11, 13, 15, 17, 23, 35, 47, 71, 95} };
+ XftFont *f=getFont(8, pix);
+
+ itsScalable=FcTrue;
+
+ itsSizes.clear();
+ itsAlphaSize=0;
+
+ if(f)
+ {
+ bool gotSizes=false;
+
+ if(itsInstalled)
+ {
+ if(FcResultMatch!=FcPatternGetBool(f->pattern, FC_SCALABLE, 0, &itsScalable))
+ itsScalable=FcFalse;
+ }
+ else
+ {
+ FT_Face face=XftLockFace(f);
+
+ if(face)
+ {
+ itsIndexCount=face->num_faces;
+ if(!(itsScalable=FT_IS_SCALABLE(face)))
+ {
+ int numSizes=face->num_fixed_sizes,
+ size;
+
+ gotSizes=true;
+
+ itsSizes.reserve(numSizes);
+
+ for (size=0; size<numSizes; size++)
+ {
+ itsSizes.push_back(face->available_sizes[size].height);
+ if (face->available_sizes[size].height<=constDefaultAlphaSize)
+ itsAlphaSize=face->available_sizes[size].height;
+ }
+ }
+ XftUnlockFace(f);
+ }
+ }
+
+ XftFontClose(KFI_DISPLAY(pix), f);
+
+ //
+ // Hmm... its not a scalable font, and its installed. So to get list of sizes, iterate through a list of standard
+ // sizes, and ask fontconfig for a font of that sizes. Then check the retured size, family, etc is what was asked
+ // for!
+ if(!itsScalable && !gotSizes)
+ {
+ itsSizes.reserve(constNumSizes);
+
+ for(int l=0; l<constNumSizeRanges && !gotSizes; ++l)
+ for(int i=0; i<constNumSizes; ++i)
+ {
+ double px;
+ int iv;
+ FcChar8 *str;
+
+ f=getFont(constSizes[l][i], pix);
+
+ if(f)
+ {
+ if(FcResultMatch==FcPatternGetDouble(f->pattern, FC_PIXEL_SIZE, 0, &px) && equal(constSizes[l][i], px) &&
+ FcResultMatch==FcPatternGetInteger(f->pattern, FC_WEIGHT, 0, &iv) && equalWeight(iv,itsWeight) &&
+ FcResultMatch==FcPatternGetInteger(f->pattern, FC_SLANT, 0, &iv) && equalSlant(iv, itsSlant) &&
+#ifndef KFI_FC_NO_WIDTHS
+ FcResultMatch==FcPatternGetInteger(f->pattern, FC_WIDTH, 0, &iv) && equalWidth(iv, itsWidth) &&
+#endif
+ FcResultMatch==FcPatternGetString(f->pattern, FC_FAMILY, 0, &str) && str &&
+ QString::fromUtf8((char *)str)==itsName)
+ {
+ itsSizes.push_back(constSizes[l][i]);
+ gotSizes=true;
+ if(constSizes[l][i]<=constDefaultAlphaSize)
+ itsAlphaSize=constSizes[l][i];
+ }
+ XftFontClose(KFI_DISPLAY(pix), f);
+ }
+ }
+ }
+ }
+
+ if(itsScalable)
+ {
+ itsSizes.reserve(constNumSizes);
+
+ for (int i=0; constScalableSizes[i]; ++i)
+ itsSizes.push_back(point2Pixel(constScalableSizes[i]));
+ itsAlphaSize=constDefaultAlphaSize;
+ }
+}
+#endif
+
+}
diff --git a/kcontrol/kfontinst/lib/FcEngine.h b/kcontrol/kfontinst/lib/FcEngine.h
new file mode 100644
index 000000000..4a09b8a55
--- /dev/null
+++ b/kcontrol/kfontinst/lib/FcEngine.h
@@ -0,0 +1,118 @@
+#ifndef __FC_ENGINE_H__
+#define __FC_ENGINE_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <qstring.h>
+#include <qvaluevector.h>
+#include <qfont.h>
+#include <kurl.h>
+#include <kdeversion.h>
+#include <fontconfig/fontconfig.h>
+
+#if (FC_VERSION<20200)
+
+#define KFI_FC_NO_WIDTHS
+#define KFI_FC_LIMITED_WEIGHTS
+
+#endif
+
+#ifdef KFI_FC_LIMITED_WEIGHTS
+
+#undef FC_WEIGHT_LIGHT
+#define FC_WEIGHT_THIN 0
+#define FC_WEIGHT_EXTRALIGHT 40
+#define FC_WEIGHT_ULTRALIGHT FC_WEIGHT_EXTRALIGHT
+#define FC_WEIGHT_LIGHT 50
+#define FC_WEIGHT_BOOK 75
+#define FC_WEIGHT_REGULAR 80
+#define FC_WEIGHT_NORMAL FC_WEIGHT_REGULAR
+#define FC_WEIGHT_SEMIBOLD FC_WEIGHT_DEMIBOLD
+#define FC_WEIGHT_EXTRABOLD 205
+#define FC_WEIGHT_ULTRABOLD FC_WEIGHT_EXTRABOLD
+#define FC_WEIGHT_HEAVY FC_WEIGHT_BLACK
+
+#endif
+
+class QPixmap;
+
+#ifdef HAVE_XFT
+typedef struct _XftFont XftFont;
+#endif
+
+namespace KFI
+{
+
+class KDE_EXPORT CFcEngine
+{
+ public:
+
+ CFcEngine();
+ ~CFcEngine();
+
+#ifdef HAVE_XFT
+ bool draw(const KURL &url, int w, int h, QPixmap &pix, int faceNo, bool thumb);
+#endif
+ int getNumIndexes() { return itsIndexCount; } // Only valid after draw has been called!
+ QString getName(const KURL &url, int faceNo=0);
+ bool getInfo(const KURL &url, int faceNo, QString &full, QString &family, QString &foundry, QString &weight,
+#ifndef KFI_FC_NO_WIDTHS
+ QString &width,
+#endif
+ QString &spacing, QString &slant);
+ QFont getQFont(const QString &name, int size);
+
+ const QValueVector<int> & sizes() const { return itsSizes; }
+ int alphaSize() const { return itsAlphaSize; }
+
+ static QString getPreviewString();
+ static void setPreviewString(const QString &str);
+ static QString getUppercaseLetters();
+ static QString getLowercaseLetters();
+ static QString getPunctuation();
+ static QString getFcString(FcPattern *pat, const char *val, int faceNo=0);
+ static QString createName(FcPattern *pat, int faceNo=0);
+ static QString weightStr(int weight, bool emptyNormal=true);
+#ifndef KFI_FC_NO_WIDTHS
+ static QString widthStr(int width, bool emptyNormal=true);
+#endif
+ static QString slantStr(int slant, bool emptyNormal=true);
+ static QString spacingStr(int spacing);
+
+ static const int constScalableSizes[];
+ static const int constDefaultAlphaSize;
+
+ private:
+
+ bool parseUrl(const KURL &url, int faceNo, bool all=false);
+ void parseName(const QString &name, int faceNo, bool all=false);
+#ifdef HAVE_XFT
+ XftFont * getFont(int size, QPixmap *pix=NULL);
+ void getSizes(QPixmap *pix=NULL);
+#endif
+
+ private:
+
+ bool itsInstalled;
+ QString itsName,
+ itsDescriptiveName,
+ itsFoundry;
+ int itsIndex,
+ itsIndexCount,
+ itsWeight,
+#ifndef KFI_FC_NO_WIDTHS
+ itsWidth,
+#endif
+ itsSlant,
+ itsSpacing,
+ itsAlphaSize;
+ QValueVector<int> itsSizes;
+ KURL itsLastUrl;
+ FcBool itsScalable;
+};
+
+}
+
+#endif
diff --git a/kcontrol/kfontinst/lib/KfiConstants.h b/kcontrol/kfontinst/lib/KfiConstants.h
new file mode 100644
index 000000000..fa7f6f1a0
--- /dev/null
+++ b/kcontrol/kfontinst/lib/KfiConstants.h
@@ -0,0 +1,73 @@
+#ifndef __KFI_CONSTANTS_H__
+#define __KFI_CONSTANTS_H__
+
+#include <klocale.h>
+
+#define KFI_CATALOGUE "kfontinst"
+
+// io-slave
+#define KFI_KIO_FONTS_PROTOCOL "fonts"
+#define KFI_KIO_FONTS_USER I18N_NOOP("Personal")
+#define KFI_KIO_FONTS_SYS I18N_NOOP("System")
+#define KFI_KIO_NO_CLEAR "?noclear"
+
+// Config
+#define KFI_UI_CFG_FILE KFI_CATALOGUE"uirc"
+#define KFI_CFG_FILE KFI_CATALOGUE"rc"
+#define KFI_ROOT_CFG_DIR "/etc/fonts/"
+#define KFI_ROOT_CFG_FILE KFI_ROOT_CFG_DIR KFI_CFG_FILE
+#define KFI_CFG_X_KEY "ConfigureX"
+#define KFI_CFG_GS_KEY "ConfigureGS"
+#define KFI_DEFAULT_CFG_X true
+#define KFI_DEFAULT_CFG_GS false
+
+// KIO::special
+
+namespace KFI
+{
+
+enum ESpecial
+{
+ SPECIAL_RECONFIG = 0,
+ SPECIAL_RESCAN = 1
+};
+
+}
+
+// Font name...
+#define KFI_WEIGHT_THIN I18N_NOOP("Thin")
+#define KFI_WEIGHT_EXTRALIGHT I18N_NOOP("ExtraLight")
+#define KFI_WEIGHT_ULTRALIGHT I18N_NOOP("UltraLight")
+#define KFI_WEIGHT_LIGHT I18N_NOOP("Light")
+#define KFI_WEIGHT_REGULAR I18N_NOOP("Regular")
+#define KFI_WEIGHT_NORMAL I18N_NOOP("Normal")
+#define KFI_WEIGHT_MEDIUM I18N_NOOP("Medium")
+#define KFI_WEIGHT_DEMIBOLD I18N_NOOP("DemiBold")
+#define KFI_WEIGHT_SEMIBOLD I18N_NOOP("SemiBold")
+#define KFI_WEIGHT_BOLD I18N_NOOP("Bold")
+#define KFI_WEIGHT_EXTRABOLD I18N_NOOP("ExtraBold")
+#define KFI_WEIGHT_ULTRABOLD I18N_NOOP("UltraBold")
+#define KFI_WEIGHT_BLACK I18N_NOOP("Black")
+#define KFI_WEIGHT_HEAVY I18N_NOOP("Heavy")
+
+#define KFI_SLANT_ROMAN I18N_NOOP("Roman")
+#define KFI_SLANT_ITALIC I18N_NOOP("Italic")
+#define KFI_SLANT_OBLIQUE I18N_NOOP("Oblique")
+
+#define KFI_WIDTH_ULTRACONDENSED I18N_NOOP("UltraCondensed")
+#define KFI_WIDTH_EXTRACONDENSED I18N_NOOP("ExtraCondensed")
+#define KFI_WIDTH_CONDENSED I18N_NOOP("Condensed")
+#define KFI_WIDTH_SEMICONDENSED I18N_NOOP("SemiCondensed")
+#define KFI_WIDTH_NORMAL I18N_NOOP("Normal")
+#define KFI_WIDTH_SEMIEXPANDED I18N_NOOP("SemiExpanded")
+#define KFI_WIDTH_EXPANDED I18N_NOOP("Expanded")
+#define KFI_WIDTH_EXTRAEXPANDED I18N_NOOP("ExtraExpanded")
+#define KFI_WIDTH_ULTRAEXPANDED I18N_NOOP("UltraExpanded")
+
+#define KFI_SPACING_MONO I18N_NOOP("Monospaced")
+#define KFI_SPACING_CHARCELL I18N_NOOP("Charcell")
+#define KFI_SPACING_PROPORTIONAL I18N_NOOP("Proportional")
+
+#define KFI_UNKNOWN_FOUNDRY I18N_NOOP("Unknown")
+
+#endif
diff --git a/kcontrol/kfontinst/lib/Makefile.am b/kcontrol/kfontinst/lib/Makefile.am
new file mode 100644
index 000000000..55349b149
--- /dev/null
+++ b/kcontrol/kfontinst/lib/Makefile.am
@@ -0,0 +1,14 @@
+lib_LTLIBRARIES = libkfontinst.la
+
+libkfontinst_la_SOURCES = \
+Misc.cpp \
+FcEngine.cpp
+
+noinst_HEADERS = \
+Misc.h \
+FcEngine.h \
+KfiConstants.h
+
+libkfontinst_la_LIBADD = $(LIB_KDECORE) $(LIBFONTCONFIG_LIBS) $(LIBFREETYPE_LIBS) $(LIB_KIO) $(LIBXFT_LIB)
+libkfontinst_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIBFONTCONFIG_RPATH) $(LIBFREETYPE_RPATH) -no-undefined
+AM_CPPFLAGS= $(all_includes) $(LIBFREETYPE_CFLAGS) $(LIBFONTCONFIG_CFLAGS) -D_LARGEFILE64_SOURCE
diff --git a/kcontrol/kfontinst/lib/Misc.cpp b/kcontrol/kfontinst/lib/Misc.cpp
new file mode 100644
index 000000000..4606ad0ca
--- /dev/null
+++ b/kcontrol/kfontinst/lib/Misc.cpp
@@ -0,0 +1,238 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Namespace : KFI::Misc
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 01/05/2001
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2001, 2002, 2003, 2004
+////////////////////////////////////////////////////////////////////////////////
+
+#include "Misc.h"
+#include <qfile.h>
+#include <kprocess.h>
+#include <kstandarddirs.h>
+#include <klargefile.h>
+#include <kio/netaccess.h>
+#include <unistd.h>
+
+namespace KFI
+{
+
+namespace Misc
+{
+
+QString linkedTo(const QString &i)
+{
+ QString d;
+
+ if(isLink(i))
+ {
+ char buffer[1000];
+ int n=readlink(QFile::encodeName(i), buffer, 1000);
+
+ if(n!=-1)
+ {
+ buffer[n]='\0';
+ d=buffer;
+ }
+ }
+
+ return d;
+}
+
+QString dirSyntax(const QString &d)
+{
+ if(!d.isEmpty())
+ {
+ QString ds(d);
+
+ ds.replace("//", "/");
+
+ int slashPos=ds.findRev('/');
+
+ if(slashPos!=(((int)ds.length())-1))
+ ds.append('/');
+
+ return ds;
+ }
+
+ return d;
+}
+
+QString xDirSyntax(const QString &d)
+{
+ if(!d.isEmpty())
+ {
+ QString ds(d);
+
+ ds.replace("//", "/");
+
+ int slashPos=ds.findRev('/');
+
+ if(slashPos==(((int)ds.length())-1))
+ ds.remove(slashPos, 1);
+ return ds;
+ }
+
+ return d;
+}
+
+QString getDir(const QString &f)
+{
+ QString d(f);
+
+ int slashPos=d.findRev('/');
+
+ if(slashPos!=-1)
+ d.remove(slashPos+1, d.length());
+
+ return dirSyntax(d);
+}
+
+QString getFile(const QString &f)
+{
+ QString d(f);
+
+ int slashPos=d.findRev('/');
+
+ if(slashPos!=-1)
+ d.remove(0, slashPos+1);
+
+ return d;
+}
+
+bool createDir(const QString &dir)
+{
+ //
+ // Clear any umask before dir is created
+ mode_t oldMask=umask(0000);
+ bool status=KStandardDirs::makeDir(dir, DIR_PERMS);
+ // Reset umask
+ ::umask(oldMask);
+ return status;
+}
+
+bool doCmd(const QString &cmd, const QString &p1, const QString &p2, const QString &p3)
+{
+ KProcess proc;
+
+ proc << cmd;
+
+ if(!p1.isEmpty())
+ proc << p1;
+ if(!p2.isEmpty())
+ proc << p2;
+ if(!p3.isEmpty())
+ proc << p3;
+
+ proc.start(KProcess::Block);
+
+ return proc.normalExit() && proc.exitStatus()==0;
+}
+
+QString changeExt(const QString &f, const QString &newExt)
+{
+ QString newStr(f);
+ int dotPos=newStr.findRev('.');
+
+ if(-1==dotPos)
+ newStr+=QChar('.')+newExt;
+ else
+ {
+ newStr.remove(dotPos+1, newStr.length());
+ newStr+=newExt;
+ }
+ return newStr;
+}
+
+void createBackup(const QString &f)
+{
+ const QString constExt(".bak");
+
+ if(!fExists(f+constExt) && fExists(f))
+ doCmd("cp", "-f", f, f+constExt);
+}
+
+//
+// Get a list of files associated with a file, e.g.:
+//
+// File: /home/a/courier.pfa
+//
+// Associated: /home/a/courier.afm /home/a/courier.pfm
+//
+void getAssociatedUrls(const KURL &url, KURL::List &list, bool afmAndPfm, QWidget *widget)
+{
+ const char *afm[]={"afm", "AFM", "Afm", "AFm", "AfM", "aFM", "aFm", "afM", NULL},
+ *pfm[]={"pfm", "PFM", "Pfm", "PFm", "PfM", "pFM", "pFm", "pfM", NULL};
+ bool gotAfm=false,
+ localFile=url.isLocalFile();
+ int e;
+
+ for(e=0; afm[e]; ++e)
+ {
+ KURL statUrl(url);
+ KIO::UDSEntry uds;
+
+ statUrl.setPath(changeExt(url.path(), afm[e]));
+
+ if(localFile ? fExists(statUrl.path()) : KIO::NetAccess::stat(statUrl, uds, widget))
+ {
+ list.append(statUrl);
+ gotAfm=true;
+ break;
+ }
+ }
+
+ if(afmAndPfm || !gotAfm)
+ for(e=0; pfm[e]; ++e)
+ {
+ KURL statUrl(url);
+ KIO::UDSEntry uds;
+
+ statUrl.setPath(changeExt(url.path(), pfm[e]));
+ if(localFile ? fExists(statUrl.path()) : KIO::NetAccess::stat(statUrl, uds, widget))
+ {
+ list.append(statUrl);
+ break;
+ }
+ }
+}
+
+time_t getTimeStamp(const QString &item)
+{
+ KDE_struct_stat info;
+
+ return !item.isEmpty() && 0==KDE_lstat(QFile::encodeName(item), &info) ? info.st_mtime : 0;
+}
+
+
+bool check(const QString &path, unsigned int fmt, bool checkW)
+{
+ KDE_struct_stat info;
+ QCString pathC(QFile::encodeName(path));
+
+ return 0==KDE_lstat(pathC, &info) && (info.st_mode&S_IFMT)==fmt && (!checkW || 0==::access(pathC, W_OK));
+}
+
+}
+
+}
diff --git a/kcontrol/kfontinst/lib/Misc.h b/kcontrol/kfontinst/lib/Misc.h
new file mode 100644
index 000000000..a624f44f9
--- /dev/null
+++ b/kcontrol/kfontinst/lib/Misc.h
@@ -0,0 +1,76 @@
+#ifndef __MISC_H__
+#define __MISC_H__
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Namespace : KFI::Misc
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 01/05/2001
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2001, 2002, 2003
+////////////////////////////////////////////////////////////////////////////////
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <kurl.h>
+
+class QWidget;
+
+namespace KFI
+{
+
+namespace Misc
+{
+ enum EConstants
+ {
+ FILE_PERMS = 0644,
+ DIR_PERMS = 0755
+ };
+
+ extern KDE_EXPORT bool check(const QString &path, unsigned int fmt, bool checkW=false);
+ inline KDE_EXPORT bool fExists(const QString &p) { return check(p, S_IFREG, false); }
+ inline KDE_EXPORT bool dExists(const QString &p) { return check(p, S_IFDIR, false); }
+ inline KDE_EXPORT bool fWritable(const QString &p) { return check(p, S_IFREG, true); }
+ inline KDE_EXPORT bool dWritable(const QString &p) { return check(p, S_IFDIR, true); }
+ inline KDE_EXPORT bool isLink(const QString &i) { return check(i, S_IFLNK, false); }
+ extern KDE_EXPORT QString linkedTo(const QString &i);
+ extern KDE_EXPORT QString dirSyntax(const QString &d); // Has trailing slash: /file/path/
+ extern KDE_EXPORT QString xDirSyntax(const QString &d); // No trailing slash: /file/path
+ inline KDE_EXPORT QString fileSyntax(const QString &f) { return xDirSyntax(f); }
+ extern KDE_EXPORT QString getDir(const QString &f);
+ extern KDE_EXPORT QString getFile(const QString &f);
+ extern KDE_EXPORT bool createDir(const QString &dir);
+ extern KDE_EXPORT QString changeExt(const QString &f, const QString &newExt);
+ extern KDE_EXPORT bool doCmd(const QString &cmd, const QString &p1=QString::null, const QString &p2=QString::null, const QString &p3=QString::null);
+ inline KDE_EXPORT bool root() { return 0==getuid(); }
+ extern KDE_EXPORT void getAssociatedUrls(const KURL &url, KURL::List &list, bool afmAndPfm=true, QWidget *widget=NULL);
+ extern KDE_EXPORT void createBackup(const QString &f);
+ extern KDE_EXPORT time_t getTimeStamp(const QString &item);
+}
+
+}
+
+#endif
diff --git a/kcontrol/kfontinst/thumbnail/FontThumbnail.cpp b/kcontrol/kfontinst/thumbnail/FontThumbnail.cpp
new file mode 100644
index 000000000..86794377b
--- /dev/null
+++ b/kcontrol/kfontinst/thumbnail/FontThumbnail.cpp
@@ -0,0 +1,73 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : KFI::CFontThumbnail
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 02/08/2003
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2003, 2004
+////////////////////////////////////////////////////////////////////////////////
+
+#include "FontThumbnail.h"
+#include "KfiConstants.h"
+#include <qimage.h>
+#include <qbitmap.h>
+#include <qpainter.h>
+#include <kiconloader.h>
+#include <kglobalsettings.h>
+#include <klocale.h>
+#include <kurl.h>
+
+extern "C"
+{
+ KDE_EXPORT ThumbCreator *new_creator()
+ {
+ return new KFI::CFontThumbnail;
+ }
+}
+
+namespace KFI
+{
+
+CFontThumbnail::CFontThumbnail()
+{
+ KGlobal::locale()->insertCatalogue(KFI_CATALOGUE);
+}
+
+bool CFontThumbnail::create(const QString &path, int width, int height, QImage &img)
+{
+ QPixmap pix;
+
+ if(itsEngine.draw(KURL(path), width, height, pix, 0, true))
+ {
+ img=pix.convertToImage();
+ return true;
+ }
+
+ return false;
+}
+
+ThumbCreator::Flags CFontThumbnail::flags() const
+{
+ return DrawFrame;
+}
+
+}
diff --git a/kcontrol/kfontinst/thumbnail/FontThumbnail.h b/kcontrol/kfontinst/thumbnail/FontThumbnail.h
new file mode 100644
index 000000000..c2d1294e4
--- /dev/null
+++ b/kcontrol/kfontinst/thumbnail/FontThumbnail.h
@@ -0,0 +1,55 @@
+#ifndef __FONT_THUMBNAIL__H__
+#define __FONT_THUMBNAIL__H__
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : KFI::CFontThumbnail
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 02/08/2003
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2003, 2004
+////////////////////////////////////////////////////////////////////////////////
+
+#include <kio/thumbcreator.h>
+#include "FcEngine.h"
+
+namespace KFI
+{
+
+class CFontThumbnail : public ThumbCreator
+{
+ public:
+
+ CFontThumbnail();
+ ~CFontThumbnail() {}
+
+ bool create(const QString &path, int width, int height, QImage &img);
+ Flags flags() const;
+
+ private:
+
+ CFcEngine itsEngine;
+};
+
+}
+
+#endif
diff --git a/kcontrol/kfontinst/thumbnail/Makefile.am b/kcontrol/kfontinst/thumbnail/Makefile.am
new file mode 100644
index 000000000..c7608e843
--- /dev/null
+++ b/kcontrol/kfontinst/thumbnail/Makefile.am
@@ -0,0 +1,14 @@
+kde_module_LTLIBRARIES = fontthumbnail.la
+
+fontthumbnail_la_SOURCES = FontThumbnail.cpp
+fontthumbnail_la_LIBADD = $(LIBFREETYPE_LIBS) $(LIB_KDECORE) $(LIB_KIO) ../lib/libkfontinst.la
+fontthumbnail_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIBFREETYPE_RPATH) -module $(KDE_PLUGIN)
+METASOURCES = AUTO
+
+noinst_HEADERS = FontThumbnail.h
+
+kdelnkdir = $(kde_servicesdir)
+
+kde_services_DATA = fontthumbnail.desktop
+
+AM_CPPFLAGS= -I$(srcdir)/../lib -I$(srcdir)/../../fonts $(all_includes) $(LIBFREETYPE_CFLAGS)
diff --git a/kcontrol/kfontinst/thumbnail/fontthumbnail.desktop b/kcontrol/kfontinst/thumbnail/fontthumbnail.desktop
new file mode 100644
index 000000000..cdda5c4d1
--- /dev/null
+++ b/kcontrol/kfontinst/thumbnail/fontthumbnail.desktop
@@ -0,0 +1,85 @@
+[Desktop Entry]
+Type=Service
+Name=Font Files
+Name[af]=Skrif tipe Lêers
+Name[ar]=ملفات المحرف
+Name[az]=Yazı Növü Faylları
+Name[be]=Файлы шрыфтоў
+Name[bg]=Файлове с шрифтове
+Name[bn]=ফন্ট ফাইল
+Name[br]=Restroù Nodrezhoù
+Name[bs]=Datoteke sa fontovima
+Name[ca]=Fitxers de lletres
+Name[cs]=Soubory s písmy
+Name[csb]=Lopczi fòntów
+Name[cy]=Ffeiliau Ffont
+Name[da]=Skrifttypefiler
+Name[de]=Schriftdatei
+Name[el]=Αρχεία γραμματοσειρών
+Name[eo]=Tipardosierojn
+Name[es]=Archivos de tipos de letra
+Name[et]=Fondifailid
+Name[eu]=Letra-tipo fitxategiak
+Name[fa]=پروندۀ قلمها
+Name[fi]=Kirjasintiedostot
+Name[fr]=Fichiers de polices
+Name[fy]=Lettertypetriemmen
+Name[ga]=Comhaid Chlófhoirne
+Name[gl]=Ficheiros de Tipografias
+Name[he]=קבצי גופנים
+Name[hi]=फ़ॉन्ट फ़ाइलें
+Name[hr]=Datoteke fontova
+Name[hu]=Betűtípusfájlok
+Name[id]=Berkas Font
+Name[is]=Leturskrár
+Name[it]=File dei tipi di carattere
+Name[ja]=フォントファイル
+Name[ka]=ფონტების ფაილები
+Name[kk]=Қаріп файлдары
+Name[km]=ឯកសារ​ពុម្ពអក្សរ
+Name[ko]=글꼴 파일
+Name[lo]=ຄົ້ນຫາແຟ້ມ
+Name[lt]=Šriftų bylos
+Name[lv]=Fontu faili
+Name[mk]=Датотеки со фонтови
+Name[mn]=Бичгийн файл
+Name[ms]=Fail Fon
+Name[mt]=Fajls tal-fonts
+Name[nb]=Skrifttypefiler
+Name[nds]=Schriftoortdateien
+Name[ne]=फन्ट फाइल
+Name[nl]=Lettertypebestanden
+Name[nn]=Skriftfiler
+Name[nso]=Difaele tsa Fonto
+Name[pa]=ਫੋਂਟ ਫਾਇਲਾਂ
+Name[pl]=Pliki czcionek
+Name[pt]=Ficheiros de Tipos de Letra
+Name[pt_BR]=Arquivos de fonte
+Name[ro]=Fișiere font
+Name[ru]=Файлы шрифтов
+Name[rw]=Amadosiye y'Imyandikire
+Name[se]=Fontafiillat
+Name[sk]=Súbory písiem
+Name[sl]=Datoteke s pisavami
+Name[sr]=Фајлови фонтова
+Name[sr@Latn]=Fajlovi fontova
+Name[sv]=Teckensnittsfiler
+Name[ta]=எழுத்துரு கோப்புகள்
+Name[tg]=Файлҳои ҳарф
+Name[th]=แฟ้มแบบอักษร
+Name[tr]=Yazıtipi Dosyaları
+Name[tt]=Yazu Biremnäre
+Name[uk]=Файли шрифтів
+Name[uz]=Shrift-fayllari
+Name[uz@cyrillic]=Шрифт-файллари
+Name[ven]=Dzifaela dza Fontu
+Name[vi]=Tập tin Phông chữ
+Name[wa]=Fitchîs fontes
+Name[xh]=Iifayile Zohlobo lwamagama
+Name[zh_CN]=字体文件
+Name[zh_TW]=字型檔案
+Name[zu]=Amafayela ohlobo lwamagama
+ServiceTypes=ThumbCreator
+MimeTypes=application/x-font-ttf,application/x-font-type1,application/x-font-bdf,application/x-font-pcf,application/x-font-otf,application/x-font-ttc
+X-KDE-Library=fontthumbnail
+CacheThumbnail=false
diff --git a/kcontrol/kfontinst/viewpart/FontPreview.cpp b/kcontrol/kfontinst/viewpart/FontPreview.cpp
new file mode 100644
index 000000000..ddd8171cb
--- /dev/null
+++ b/kcontrol/kfontinst/viewpart/FontPreview.cpp
@@ -0,0 +1,118 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : KFI::CFontPreview
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 04/11/2001
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2001, 2002, 2003, 2004
+////////////////////////////////////////////////////////////////////////////////
+
+#include "FontPreview.h"
+#include <kapplication.h>
+#include <klocale.h>
+#include <qpainter.h>
+#include <qimage.h>
+#include <stdlib.h>
+
+namespace KFI
+{
+
+CFontPreview::CFontPreview(QWidget *parent, const char *name)
+ : QWidget(parent, name),
+ itsCurrentFace(1),
+ itsLastWidth(0),
+ itsLastHeight(0),
+ itsBgndCol(eraseColor())
+{
+}
+
+void CFontPreview::showFont(const KURL &url)
+{
+ itsCurrentUrl=url;
+ showFace(1);
+}
+
+void CFontPreview::showFace(int face)
+{
+ itsCurrentFace=face;
+ showFont();
+}
+
+void CFontPreview::showFont()
+{
+ itsLastWidth=width();
+ itsLastHeight=height();
+
+ if(!itsCurrentUrl.isEmpty() &&
+ itsEngine.draw(itsCurrentUrl, itsLastWidth, itsLastHeight, itsPixmap, itsCurrentFace-1, false))
+ {
+ setEraseColor(Qt::white);
+ update();
+ emit status(true);
+ }
+ else
+ {
+ QPixmap nullPix;
+
+ setEraseColor(itsBgndCol);
+ itsPixmap=nullPix;
+ update();
+ emit status(false);
+ }
+}
+
+void CFontPreview::paintEvent(QPaintEvent *)
+{
+ QPainter paint(this);
+
+ if(itsPixmap.isNull())
+ {
+ if(!itsCurrentUrl.isEmpty())
+ {
+ paint.setPen(kapp->palette().active().text());
+ paint.drawText(rect(), AlignCenter, i18n(" No preview available"));
+ }
+ }
+ else
+ {
+ static const int constStepSize=16;
+
+ if(abs(width()-itsLastWidth)>constStepSize || abs(height()-itsLastHeight)>constStepSize)
+ showFont();
+ else
+ paint.drawPixmap(0, 0, itsPixmap);
+ }
+}
+
+QSize CFontPreview::sizeHint() const
+{
+ return QSize(132, 132);
+}
+
+QSize CFontPreview::minimumSizeHint() const
+{
+ return QSize(32, 32);
+}
+
+}
+
+#include "FontPreview.moc"
diff --git a/kcontrol/kfontinst/viewpart/FontPreview.h b/kcontrol/kfontinst/viewpart/FontPreview.h
new file mode 100644
index 000000000..673adeb2d
--- /dev/null
+++ b/kcontrol/kfontinst/viewpart/FontPreview.h
@@ -0,0 +1,83 @@
+#ifndef __FONT_PREVIEW_H__
+#define __FONT_PREVIEW_H__
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : KFI::CFontPreview
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 04/11/2001
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2001, 2002, 2003, 2004
+////////////////////////////////////////////////////////////////////////////////
+
+#include <qstring.h>
+#include <qpixmap.h>
+#include <qsize.h>
+#include <qwidget.h>
+#include <qcolor.h>
+#include <kurl.h>
+#include "FcEngine.h"
+
+namespace KFI
+{
+
+class CFontPreview : public QWidget
+{
+ Q_OBJECT
+
+ public:
+
+ CFontPreview(QWidget *parent, const char *name=NULL);
+ virtual ~CFontPreview() {}
+
+ void paintEvent(QPaintEvent *);
+ QSize sizeHint() const;
+ QSize minimumSizeHint() const;
+
+ void showFont(const KURL &url);
+ void showFont();
+
+ CFcEngine & engine() { return itsEngine; }
+
+ public slots:
+
+ void showFace(int face);
+
+ signals:
+
+ void status(bool);
+
+ private:
+
+ CFcEngine itsEngine;
+ QPixmap itsPixmap;
+ KURL itsCurrentUrl;
+ int itsCurrentFace,
+ itsLastWidth,
+ itsLastHeight;
+ QColor itsBgndCol;
+ QString itsFontName;
+};
+
+}
+
+#endif
diff --git a/kcontrol/kfontinst/viewpart/FontViewPart.cpp b/kcontrol/kfontinst/viewpart/FontViewPart.cpp
new file mode 100644
index 000000000..aaa3bc5ff
--- /dev/null
+++ b/kcontrol/kfontinst/viewpart/FontViewPart.cpp
@@ -0,0 +1,282 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : KFI::CFontViewPart
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 03/08/2002
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2002, 2003, 2004
+////////////////////////////////////////////////////////////////////////////////
+
+#include "FontViewPart.h"
+#include "FontPreview.h"
+#include "Misc.h"
+#include "KfiConstants.h"
+#include "KfiPrint.h"
+#include <klocale.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qframe.h>
+#include <qfile.h>
+#include <qlabel.h>
+#include <qpainter.h>
+#include <qpaintdevicemetrics.h>
+#include <qvalidator.h>
+#include <qregexp.h>
+#include <qsettings.h>
+#include <qstringlist.h>
+#include <qtimer.h>
+#include <kio/netaccess.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <knuminput.h>
+#include <kstdaction.h>
+#include <kaction.h>
+#include <kinputdialog.h>
+#include <kdialog.h>
+#include <kprinter.h>
+#include <fontconfig/fontconfig.h>
+
+static KURL getDest(const KURL &url, bool system)
+{
+ return KURL(KFI::Misc::root()
+ ? QString("fonts:/") + url.fileName()
+ : QString("fonts:/") + QString(system ? i18n(KFI_KIO_FONTS_SYS) : i18n(KFI_KIO_FONTS_USER))
+ + QChar('/') + url.fileName());
+}
+
+namespace KFI
+{
+
+CFontViewPart::CFontViewPart(QWidget *parent, const char *name)
+{
+ bool kcm=0==strcmp(name, "kcmfontinst");
+
+ itsFrame=new QFrame(parent, "frame");
+
+ QFrame *previewFrame=new QFrame(itsFrame);
+
+ itsToolsFrame=new QFrame(itsFrame);
+
+ QVBoxLayout *layout=new QVBoxLayout(itsFrame, kcm ? 0 : KDialog::marginHint(), kcm ? 0 : KDialog::spacingHint());
+ QGridLayout *previewLayout=new QGridLayout(previewFrame, 1, 1, 1, 1);
+ QHBoxLayout *toolsLayout=new QHBoxLayout(itsToolsFrame, 0, KDialog::spacingHint());
+
+ itsFrame->setFrameShape(QFrame::NoFrame);
+ itsFrame->setFocusPolicy(QWidget::ClickFocus);
+ itsToolsFrame->setFrameShape(QFrame::NoFrame);
+ previewFrame->setFrameShadow(kcm ? QFrame::Sunken : QFrame::Raised);
+ previewFrame->setFrameShape(QFrame::Panel);
+ setInstance(new KInstance("kfontview"));
+
+ itsPreview=new CFontPreview(previewFrame, "FontViewPart::Preview");
+ itsPreview->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
+ itsFaceLabel=new QLabel(i18n("Face:"), itsToolsFrame);
+ itsFaceSelector=new KIntNumInput(1, itsToolsFrame);
+ itsInstallButton=new QPushButton(i18n("Install..."), itsToolsFrame, "button");
+ itsInstallButton->hide();
+ previewLayout->addWidget(itsPreview, 0, 0);
+ layout->addWidget(previewFrame);
+ layout->addWidget(itsToolsFrame);
+ toolsLayout->addWidget(itsFaceLabel);
+ toolsLayout->addWidget(itsFaceSelector);
+ itsFaceLabel->hide();
+ itsFaceSelector->hide();
+ toolsLayout->addItem(new QSpacerItem(5, 5, QSizePolicy::MinimumExpanding, QSizePolicy::Minimum));
+ toolsLayout->addWidget(itsInstallButton);
+ itsToolsFrame->hide();
+ connect(itsPreview, SIGNAL(status(bool)), SLOT(previewStatus(bool)));
+ connect(itsInstallButton, SIGNAL(clicked()), SLOT(install()));
+ connect(itsFaceSelector, SIGNAL(valueChanged(int)), itsPreview, SLOT(showFace(int)));
+
+ itsChangeTextAction=new KAction(i18n("Change Text..."), "text", KShortcut(),
+ this, SLOT(changeText()), actionCollection(), "changeText");
+ itsChangeTextAction->setEnabled(false);
+ itsPrintAction=KStdAction::print(this, SLOT(print()), actionCollection(), "print");
+ itsPrintAction->setEnabled(false);
+
+ setXMLFile("kfontviewpart.rc");
+ setWidget(itsFrame);
+}
+
+bool CFontViewPart::openURL(const KURL &url)
+{
+ if (!url.isValid() || !closeURL())
+ return false;
+
+ if(KFI_KIO_FONTS_PROTOCOL==url.protocol() || url.isLocalFile())
+ {
+ m_url=url;
+ emit started(0);
+ m_file = m_url.path();
+ bool ret=openFile();
+ if (ret)
+ {
+ emit completed();
+ emit setWindowCaption(m_url.prettyURL());
+ }
+ return ret;
+ }
+ else
+ return ReadOnlyPart::openURL(url);
+}
+
+bool CFontViewPart::openFile()
+{
+ // NOTE: Cant do the real open here, as dont seem to be able to use KIO::NetAccess functions during initial start-up.
+ // Bug report 111535 indicates that calling "konqueror <font>" crashes.
+ QTimer::singleShot(0, this, SLOT(timeout()));
+ return true;
+}
+
+void CFontViewPart::timeout()
+{
+ bool showFs=false,
+ isFonts=KFI_KIO_FONTS_PROTOCOL==m_url.protocol();
+
+ itsShowInstallButton=false;
+
+ if(isFonts)
+ FcInitReinitialize();
+ else
+ {
+ KURL destUrl;
+
+ //
+ // Not from fonts:/, so try to see if font is already installed...
+ if(Misc::root())
+ {
+ destUrl=QString("fonts:/")+itsPreview->engine().getName(m_url);
+ itsShowInstallButton=!KIO::NetAccess::exists(destUrl, true, itsFrame->parentWidget());
+ }
+ else
+ {
+ destUrl=QString("fonts:/")+i18n(KFI_KIO_FONTS_SYS)+QChar('/')+itsPreview->engine().getName(m_url);
+ if(KIO::NetAccess::exists(destUrl, true, itsFrame->parentWidget()))
+ itsShowInstallButton=false;
+ else
+ {
+ destUrl=QString("fonts:/")+i18n(KFI_KIO_FONTS_USER)+QChar('/')+itsPreview->engine().getName(m_url);
+ itsShowInstallButton=!KIO::NetAccess::exists(destUrl, true, itsFrame->parentWidget());
+ }
+ }
+ }
+
+ itsPreview->showFont(isFonts ? m_url : m_file);
+
+ if(!isFonts && itsPreview->engine().getNumIndexes()>1)
+ {
+ showFs=true;
+ itsFaceSelector->setRange(1, itsPreview->engine().getNumIndexes(), 1, false);
+ }
+
+ itsFaceLabel->setShown(showFs);
+ itsFaceSelector->setShown(showFs);
+ itsToolsFrame->hide();
+}
+
+void CFontViewPart::previewStatus(bool st)
+{
+ itsInstallButton->setShown(st && itsShowInstallButton);
+ itsToolsFrame->setShown(itsInstallButton->isShown()||itsFaceSelector->isShown());
+ itsChangeTextAction->setEnabled(st);
+ itsPrintAction->setEnabled(st && KFI_KIO_FONTS_PROTOCOL==m_url.protocol());
+}
+
+void CFontViewPart::install()
+{
+ int resp=Misc::root() ? KMessageBox::Yes
+ : KMessageBox::questionYesNoCancel(itsFrame,
+ i18n("Where do you wish to install \"%1\" (%2)?\n"
+ "\"%3\" - only accessible to you, or\n"
+ "\"%4\" - accessible to all (requires administrator "
+ "password)")
+ .arg(itsPreview->engine().getName(m_url))
+ .arg(m_url.fileName())
+ .arg(i18n(KFI_KIO_FONTS_USER))
+ .arg(i18n(KFI_KIO_FONTS_SYS)),
+ i18n("Install"), i18n(KFI_KIO_FONTS_USER),
+ i18n(KFI_KIO_FONTS_SYS));
+
+ if(KMessageBox::Cancel!=resp)
+ {
+ KURL destUrl(getDest(m_url, KMessageBox::No==resp));
+
+ if(KIO::NetAccess::copy(m_url, destUrl, itsFrame->parentWidget()))
+ {
+ //
+ // OK file copied, now look for any AFM or PFM file...
+ KURL::List urls;
+
+ Misc::getAssociatedUrls(m_url, urls);
+
+ if(urls.count())
+ {
+ KURL::List::Iterator it,
+ end=urls.end();
+
+ for(it=urls.begin(); it!=end; ++it)
+ {
+ destUrl=getDest(*it, KMessageBox::No==resp);
+ KIO::NetAccess::copy(*it, destUrl, itsFrame->parentWidget());
+ }
+ }
+
+ KMessageBox::information(itsFrame, i18n("%1:%2 successfully installed.").arg(m_url.protocol())
+ .arg(m_url.path()), i18n("Success"),
+ "FontViewPart_DisplayInstallationSuccess");
+ itsShowInstallButton=false;
+ itsInstallButton->setShown(itsShowInstallButton);
+ }
+ else
+ KMessageBox::error(itsFrame, i18n("Could not install %1:%2").arg(m_url.protocol()).arg(m_url.path()),
+ i18n("Error"));
+ }
+}
+
+void CFontViewPart::changeText()
+{
+ bool status;
+ QRegExpValidator validator(QRegExp(".*"), 0L);
+ QString oldStr(itsPreview->engine().getPreviewString()),
+ newStr(KInputDialog::getText(i18n("Preview String"), i18n("Please enter new string:"),
+ oldStr, &status, itsFrame,
+ "preview string dialog", &validator));
+
+ if(status && newStr!=oldStr)
+ {
+ itsPreview->engine().setPreviewString(newStr);
+ itsPreview->showFont();
+ }
+}
+
+void CFontViewPart::print()
+{
+ QStringList items;
+
+ items.append(itsPreview->engine().getName(m_url));
+
+ Print::printItems(items, 0, itsFrame->parentWidget(), itsPreview->engine());
+}
+
+}
+
+#include "FontViewPart.moc"
diff --git a/kcontrol/kfontinst/viewpart/FontViewPart.h b/kcontrol/kfontinst/viewpart/FontViewPart.h
new file mode 100644
index 000000000..7ffdbb8f4
--- /dev/null
+++ b/kcontrol/kfontinst/viewpart/FontViewPart.h
@@ -0,0 +1,85 @@
+#ifndef __FONT_VIEW_PART_H__
+#define __FONT_VIEW_PART_H__
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : KFI::CFontViewPart
+// Author : Craig Drummond
+// Project : K Font Installer (kfontinst-kcontrol)
+// Creation Date : 03/08/2002
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2002, 2003, 2004
+////////////////////////////////////////////////////////////////////////////////
+
+#include <kparts/part.h>
+
+class QPushButton;
+class QFrame;
+class QLabel;
+class KIntNumInput;
+class KAction;
+class KURL;
+
+namespace KFI
+{
+
+class CFontPreview;
+
+class CFontViewPart : public KParts::ReadOnlyPart
+{
+ Q_OBJECT
+
+ public:
+
+ CFontViewPart(QWidget *parent=0, const char *name=0);
+ virtual ~CFontViewPart() {}
+
+ bool openURL(const KURL &url);
+
+ protected:
+
+ bool openFile();
+
+ private slots:
+
+ void previewStatus(bool st);
+ void timeout();
+ void install();
+ void changeText();
+ void print();
+
+ private:
+
+ CFontPreview *itsPreview;
+ QPushButton *itsInstallButton;
+ QFrame *itsFrame,
+ *itsToolsFrame;
+ QLabel *itsFaceLabel;
+ KIntNumInput *itsFaceSelector;
+ KAction *itsChangeTextAction,
+ *itsPrintAction;
+ bool itsShowInstallButton;
+ int itsFace;
+};
+
+}
+
+#endif
diff --git a/kcontrol/kfontinst/viewpart/FontViewPartFactory.cpp b/kcontrol/kfontinst/viewpart/FontViewPartFactory.cpp
new file mode 100644
index 000000000..52783c1a7
--- /dev/null
+++ b/kcontrol/kfontinst/viewpart/FontViewPartFactory.cpp
@@ -0,0 +1,86 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : KFI::CFontViewPartFactory
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 03/08/2002
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2002, 2003, 2004
+////////////////////////////////////////////////////////////////////////////////
+
+#include "FontViewPartFactory.h"
+#include "FontViewPart.h"
+#include <kdebug.h>
+#include <kaboutdata.h>
+#include <kinstance.h>
+#include <assert.h>
+
+extern "C"
+{
+ KDE_EXPORT void* init_libkfontviewpart()
+ {
+ KGlobal::locale()->insertCatalogue("kfontinst");
+ return new KFI::CFontViewPartFactory;
+ }
+}
+
+namespace KFI
+{
+
+KInstance * CFontViewPartFactory::theirInstance=NULL;
+KAboutData * CFontViewPartFactory::theirAbout=NULL;
+
+CFontViewPartFactory::CFontViewPartFactory()
+{
+}
+
+CFontViewPartFactory::~CFontViewPartFactory()
+{
+ delete theirAbout;
+ theirAbout=0L;
+ delete theirInstance;
+ theirInstance=0L;
+}
+
+QObject * CFontViewPartFactory::createObject(QObject *parent, const char *name, const char *, const QStringList &)
+{
+ if(parent && !parent->isWidgetType())
+ {
+ kdDebug() << "CFontViewPartFactory: parent does not inherit QWidget" << endl;
+ return 0L;
+ }
+
+ return new CFontViewPart((QWidget*) parent, name);
+}
+
+KInstance* CFontViewPartFactory::instance()
+{
+ if(!theirInstance)
+ {
+ theirAbout = new KAboutData("fontviewpart", I18N_NOOP("CFontViewPart"), "0.1");
+ theirInstance = new KInstance(theirAbout);
+ }
+ return theirInstance;
+}
+
+}
+
+#include "FontViewPartFactory.moc"
diff --git a/kcontrol/kfontinst/viewpart/FontViewPartFactory.h b/kcontrol/kfontinst/viewpart/FontViewPartFactory.h
new file mode 100644
index 000000000..777d07ebe
--- /dev/null
+++ b/kcontrol/kfontinst/viewpart/FontViewPartFactory.h
@@ -0,0 +1,60 @@
+#ifndef __FONT_VIEW_PART_FACTORY_H__
+#define __FONT_VIEW_PART_FACTORY_H__
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : KFI::CFontViewPartFactory
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 03/08/2002
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2002, 2003, 2004
+////////////////////////////////////////////////////////////////////////////////
+
+#include <klibloader.h>
+
+class KInstance;
+class KAboutData;
+
+namespace KFI
+{
+
+class CFontViewPartFactory : public KLibFactory
+{
+ Q_OBJECT
+
+ public:
+
+ CFontViewPartFactory();
+ virtual ~CFontViewPartFactory();
+ virtual QObject *createObject(QObject *parent = 0, const char *name = 0, const char *classname = "QObject", const QStringList &args = QStringList());
+
+ static KInstance * instance();
+
+ private:
+
+ static KInstance *theirInstance;
+ static KAboutData *theirAbout;
+};
+
+}
+
+#endif
diff --git a/kcontrol/kfontinst/viewpart/FontViewerApp.cpp b/kcontrol/kfontinst/viewpart/FontViewerApp.cpp
new file mode 100644
index 000000000..5ed5cf455
--- /dev/null
+++ b/kcontrol/kfontinst/viewpart/FontViewerApp.cpp
@@ -0,0 +1,130 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Names : KFI::CFontViewerApp, KFI::CFontViewerAppMainWindow
+// Author : Craig Drummond
+// Project : K Font Installer (kfontinst-kcontrol)
+// Creation Date : 30/04/2004
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2004
+////////////////////////////////////////////////////////////////////////////////
+
+#include "FontViewerApp.h"
+#include "KfiConstants.h"
+#include <kaboutdata.h>
+#include <kcmdlineargs.h>
+#include <klibloader.h>
+#include <klocale.h>
+#include <kglobal.h>
+#include <kfiledialog.h>
+#include <kconfig.h>
+
+#define CFG_GROUP "FontViewer Settings"
+#define CFG_SIZE_KEY "Window Size"
+
+namespace KFI
+{
+
+CFontViewerAppMainWindow::CFontViewerAppMainWindow()
+ : KParts::MainWindow((QWidget *)0L)
+{
+ KLibFactory *factory=KLibLoader::self()->factory("libkfontviewpart");
+
+ if(factory)
+ {
+ KStdAction::open(this, SLOT(fileOpen()), actionCollection());
+ KStdAction::quit(kapp, SLOT(quit()), actionCollection());
+
+ itsPreview=(KParts::ReadOnlyPart *)factory->create(this, "fontvier", "KParts::ReadOnlyPart");
+
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+ KURL openURL;
+
+ if(args->count() > 0)
+ {
+ KURL url(args->url(args->count() - 1));
+
+ if(url.isValid())
+ openURL = url;
+ }
+
+ setCentralWidget(itsPreview->widget());
+ createGUI(itsPreview);
+
+ if(!openURL.isEmpty())
+ itsPreview->openURL(openURL);
+
+ QSize defSize(450, 380);
+ KConfigGroupSaver saver(kapp->config(), CFG_GROUP);
+
+ resize(kapp->config()->readSizeEntry(CFG_SIZE_KEY, &defSize));
+ show();
+ }
+ else
+ exit(0);
+}
+
+CFontViewerAppMainWindow::~CFontViewerAppMainWindow()
+{
+ KConfigGroupSaver saver(kapp->config(), CFG_GROUP);
+ kapp->config()->writeEntry(CFG_SIZE_KEY, size());
+ kapp->config()->sync();
+}
+
+void CFontViewerAppMainWindow::fileOpen()
+{
+ KURL url(KFileDialog::getOpenURL(QString::null, "application/x-font-ttf application/x-font-otf "
+ "application/x-font-ttc application/x-font-type1 "
+ "application/x-font-bdf application/x-font-pcf ",
+ this, i18n("Select Font to View")));
+ if(url.isValid())
+ itsPreview->openURL(url);
+}
+
+CFontViewerApp::CFontViewerApp()
+{
+ KGlobal::locale()->insertCatalogue(KFI_CATALOGUE);
+ setMainWidget(new CFontViewerAppMainWindow());
+}
+
+}
+
+static KCmdLineOptions options[] =
+{
+ { "+[URL]", I18N_NOOP("URL to open"), 0 },
+ KCmdLineLastOption
+};
+
+static KAboutData aboutData("kfontview", I18N_NOOP("Font Viewer"), 0, I18N_NOOP("Simple font viewer"),
+ KAboutData::License_GPL,
+ I18N_NOOP("(c) Craig Drummond, 2004"));
+
+int main(int argc, char **argv)
+{
+ KCmdLineArgs::init(argc, argv, &aboutData);
+ KCmdLineArgs::addCmdLineOptions(options);
+ KFI::CFontViewerApp::addCmdLineOptions();
+
+ KFI::CFontViewerApp app;
+
+ return app.exec();
+}
+
+#include "FontViewerApp.moc"
diff --git a/kcontrol/kfontinst/viewpart/FontViewerApp.h b/kcontrol/kfontinst/viewpart/FontViewerApp.h
new file mode 100644
index 000000000..70543a8f3
--- /dev/null
+++ b/kcontrol/kfontinst/viewpart/FontViewerApp.h
@@ -0,0 +1,68 @@
+#ifndef __FONT_VIEWER_APP_H__
+#define __FONT_VIEWER_APP_H__
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Class Name : KFI::CFontViewerApp, KFI::CFontViewAppMainWindow
+// Author : Craig Drummond
+// Project : K Font Installer (kfontinst-kcontrol)
+// Creation Date : 30/04/2004
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2004
+////////////////////////////////////////////////////////////////////////////////
+
+#include <kapplication.h>
+#include <kparts/part.h>
+#include <kparts/mainwindow.h>
+
+namespace KFI
+{
+
+class CFontViewerAppMainWindow : public KParts::MainWindow
+{
+ Q_OBJECT
+
+ public:
+
+ CFontViewerAppMainWindow();
+ virtual ~CFontViewerAppMainWindow();
+
+ public slots:
+
+ void fileOpen();
+
+ private:
+
+ KParts::ReadOnlyPart *itsPreview;
+
+};
+
+class CFontViewerApp : public KApplication
+{
+ public:
+
+ CFontViewerApp();
+ virtual ~CFontViewerApp() {}
+};
+
+}
+
+#endif
diff --git a/kcontrol/kfontinst/viewpart/KfiPrint.cpp b/kcontrol/kfontinst/viewpart/KfiPrint.cpp
new file mode 100644
index 000000000..02366922a
--- /dev/null
+++ b/kcontrol/kfontinst/viewpart/KfiPrint.cpp
@@ -0,0 +1,193 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Namespace : KFI::Print
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 14/05/2005
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2005
+////////////////////////////////////////////////////////////////////////////////
+
+#include "KfiPrint.h"
+#include "FcEngine.h"
+#include <qpainter.h>
+#include <qpaintdevicemetrics.h>
+#include <qsettings.h>
+#include <qstringlist.h>
+#include <kprinter.h>
+#include <qapplication.h>
+#include <qeventloop.h>
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+namespace KFI
+{
+
+namespace Print
+{
+
+static const int constMarginLineBefore=1;
+static const int constMarginLineAfter=2;
+static const int constMarginFont=4;
+
+inline bool sufficientSpace(int y, int pageHeight, int size)
+{
+ return (y+constMarginFont+size)<pageHeight;
+}
+
+static bool sufficientSpace(int y, int titleFontHeight, const int *sizes, int pageHeight, int size)
+{
+ int required=titleFontHeight+constMarginLineBefore+constMarginLineAfter;
+
+ for(unsigned int s=0; sizes[s]; ++s)
+ {
+ required+=sizes[s];
+ if(sizes[s+1])
+ required+=constMarginFont;
+ }
+
+ if(0==size)
+ required+=(3*(constMarginFont+CFcEngine::constDefaultAlphaSize))+constMarginLineBefore+constMarginLineAfter;
+ return (y+required)<pageHeight;
+}
+
+bool printable(const QString &mime)
+{
+ return "application/x-font-type1"==mime || "application/x-font-ttf"==mime || "application/x-font-otf"==mime ||
+ "application/x-font-ttc"==mime || "application/x-font-ghostscript"==mime;
+}
+
+void printItems(const QStringList &items, int size, QWidget *parent, CFcEngine &engine)
+{
+#ifdef HAVE_LOCALE_H
+ char *oldLocale=setlocale(LC_NUMERIC, "C"),
+#endif
+
+ KPrinter printer;
+
+ printer.setFullPage(true);
+
+ if(printer.setup(parent))
+ {
+ QPainter painter;
+ QFont sans("sans", 12, QFont::Bold);
+ QSettings settings;
+ bool entryExists,
+ embedFonts,
+ set=false;
+ QString str(engine.getPreviewString());
+
+ //
+ // Cehck whether the user has enabled font embedding...
+ embedFonts=settings.readBoolEntry("/qt/embedFonts", false, &entryExists);
+
+ // ...if not, then turn on - we may have installed new fonts, without ghostscript being informed, etc.
+ if(!entryExists || !embedFonts)
+ settings.writeEntry("/qt/embedFonts", true);
+
+ printer.setResolution(72);
+ painter.begin(&printer);
+
+ QPaintDeviceMetrics metrics(painter.device());
+ int margin=(int)((2/2.54)*metrics.logicalDpiY()), // 2 cm margins
+ pageWidth=metrics.width()-(2*margin),
+ pageHeight=metrics.height()-(2*margin),
+ y=margin,
+ oneSize[2]={size, 0};
+ const int *sizes=oneSize;
+ bool firstFont(true);
+
+ if(0==size)
+ sizes=CFcEngine::constScalableSizes;
+
+ painter.setClipping(true);
+ painter.setClipRect(margin, margin, pageWidth, pageHeight);
+
+ QStringList::ConstIterator it(items.begin()),
+ end(items.end());
+
+ for(; it!=end; ++it)
+ {
+ unsigned int s=0;
+
+ painter.setFont(sans);
+ QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput, 0);
+
+ if(!firstFont && !sufficientSpace(y, painter.fontMetrics().height(), sizes, pageHeight, size))
+ {
+ printer.newPage();
+ y=margin;
+ }
+ painter.setFont(sans);
+ y+=painter.fontMetrics().height();
+ painter.drawText(margin, y, *it);
+ y+=constMarginLineBefore;
+ painter.drawLine(margin, y, margin+pageWidth, y);
+ y+=constMarginLineAfter;
+
+ if(0==size)
+ {
+ y+=CFcEngine::constDefaultAlphaSize;
+ painter.setFont(engine.getQFont(*it, CFcEngine::constDefaultAlphaSize));
+ painter.drawText(margin, y, CFcEngine::getLowercaseLetters());
+ y+=constMarginFont+CFcEngine::constDefaultAlphaSize;
+ painter.drawText(margin, y, CFcEngine::getUppercaseLetters());
+ y+=constMarginFont+CFcEngine::constDefaultAlphaSize;
+ painter.drawText(margin, y, CFcEngine::getPunctuation());
+ y+=constMarginFont+constMarginLineBefore;
+ painter.drawLine(margin, y, margin+pageWidth, y);
+ y+=constMarginLineAfter;
+ }
+ for(; sizes[s]; ++s)
+ {
+ y+=sizes[s];
+ painter.setFont(engine.getQFont(*it, sizes[s]));
+ if(sufficientSpace(y, pageHeight, sizes[s]))
+ {
+ painter.drawText(margin, y, str);
+ if(sizes[s+1])
+ y+=constMarginFont;
+ }
+ }
+ firstFont=false;
+ y+=(s<1 || sizes[s-1]<25 ? 14 : 28);
+ }
+
+ painter.end();
+
+ //
+ // Did we change the users font settings? If so, reset to their previous values...
+ if(set)
+ if(entryExists)
+ settings.writeEntry("/qt/embedFonts", false);
+ else
+ settings.removeEntry("/qt/embedFonts");
+ }
+#ifdef HAVE_LOCALE_H
+ if(oldLocale)
+ setlocale(LC_NUMERIC, oldLocale);
+#endif
+}
+
+}
+
+}
diff --git a/kcontrol/kfontinst/viewpart/KfiPrint.h b/kcontrol/kfontinst/viewpart/KfiPrint.h
new file mode 100644
index 000000000..5b927a57a
--- /dev/null
+++ b/kcontrol/kfontinst/viewpart/KfiPrint.h
@@ -0,0 +1,49 @@
+#ifndef __PRINT_H__
+#define __PRINT_H__
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Namespace : KFI::Print
+// Author : Craig Drummond
+// Project : K Font Installer
+// Creation Date : 14/05/2005
+// Version : $Revision$ $Date$
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+////////////////////////////////////////////////////////////////////////////////
+// (C) Craig Drummond, 2005
+////////////////////////////////////////////////////////////////////////////////
+
+class QStringList;
+class QString;
+class QWidget;
+
+namespace KFI
+{
+
+class CFcEngine;
+
+namespace Print
+{
+extern void printItems(const QStringList &items, int size, QWidget *parent, CFcEngine &engine);
+extern bool printable(const QString &mime);
+}
+
+}
+
+#endif
diff --git a/kcontrol/kfontinst/viewpart/Makefile.am b/kcontrol/kfontinst/viewpart/Makefile.am
new file mode 100644
index 000000000..bfa66c696
--- /dev/null
+++ b/kcontrol/kfontinst/viewpart/Makefile.am
@@ -0,0 +1,30 @@
+noinst_LTLIBRARIES = libkfontinstprint.la
+libkfontinstprint_la_SOURCES = KfiPrint.cpp
+libkfontinstprint_la_LDFLAGS = $(all_libraries)
+libkfontinstprint_la_LIBADD = $(LIB_KDEPRINT) ../lib/libkfontinst.la
+
+kde_module_LTLIBRARIES = libkfontviewpart.la
+
+libkfontviewpart_la_SOURCES = FontViewPart.cpp FontViewPartFactory.cpp FontPreview.cpp
+libkfontviewpart_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+libkfontviewpart_la_LIBADD = $(LIB_KPARTS) libkfontinstprint.la ../lib/libkfontinst.la
+
+noinst_HEADERS = FontViewPart.h FontViewPartFactory.h FontPreview.h FontViewerApp.h KfiPrint.h
+
+kde_services_DATA = kfontviewpart.desktop
+
+AM_CPPFLAGS = -I$(srcdir)/../lib -I$(srcdir)/../../fonts $(all_includes) $(LIBFREETYPE_CFLAGS) $(LIBFONTCONFIG_CFLAGS)
+METASOURCES = AUTO
+
+kfontview_LDADD = $(LIB_KPARTS)
+kfontview_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+
+bin_PROGRAMS = kfontview
+xdg_apps_DATA = kfontview.desktop
+
+appdata_DATA = kfontviewpart.rc kfontviewui.rc
+appdatadir = $(kde_datadir)/kfontview
+
+kfontview_SOURCES = FontViewerApp.cpp
+
+
diff --git a/kcontrol/kfontinst/viewpart/kfontview.desktop b/kcontrol/kfontinst/viewpart/kfontview.desktop
new file mode 100644
index 000000000..843213221
--- /dev/null
+++ b/kcontrol/kfontinst/viewpart/kfontview.desktop
@@ -0,0 +1,100 @@
+[Desktop Entry]
+Name=KFontView
+Name[be]=Прагляд шрыфтоў
+Name[bn]=কে-ফন্ট-ভিউ
+Name[cs]=Prohlížeč písem
+Name[eo]=Tiparorigardilo
+Name[eu]=KFontWiew
+Name[he]=מציג גופנים
+Name[hi]=के-फ़ॉन्ट-व्यू
+Name[mk]=КФонтПреглед
+Name[nb]=Skriftviser
+Name[nds]=Schriftoortkieker
+Name[ne]=K फन्ट दृश्य
+Name[nn]=Skriftvisar
+Name[rw]=K-IgaragazaImyandikire
+Name[se]=Fontačájeheaddji
+Name[sk]=Prehliadač písiem
+Name[sv]=Kfontview
+Name[tg]=Намоишгари КҲарф
+Name[vi]=Trình xem phông chữ KDE
+Name[wa]=Håyneu di fontes (KFontView)
+Name[zh_CN]=字体预览
+Exec=kfontview %i %u
+Icon=fonts
+X-KDE-StartupNotify=true
+Type=Application
+MimeType=application/x-font-ttf;application/x-font-type1;application/x-font-otf;application/x-font-ttc;application/x-font-pcf;application/x-font-bdf;fonts/package;
+GenericName=Font Viewer
+GenericName[af]=Skriftipe Besigter
+GenericName[ar]=معاين المحرف
+GenericName[be]=Праглядальнік шрыфтоў
+GenericName[bg]=Преглед на шрифтове
+GenericName[bn]=ফন্ট প্রদর্শক
+GenericName[br]=Gweler Nodrezhoù
+GenericName[bs]=Preglednik fontova
+GenericName[ca]=Visor de lletres
+GenericName[cs]=Prohlížeč písem
+GenericName[csb]=Przezérnik fòntów
+GenericName[cy]=Gwelydd Wynebfathau
+GenericName[da]=Skrifttype-fremviser
+GenericName[de]=Schriftartenbetrachter
+GenericName[el]=Προβολέας γραμματοσειρών
+GenericName[eo]=Tipara rigardilo
+GenericName[es]=Visor de tipos de letra
+GenericName[et]=Fontide vaataja
+GenericName[eu]=Letra-tipoen ikusgailua
+GenericName[fa]=مشاهده‌گر قلم
+GenericName[fi]=Kirjasinten näytin
+GenericName[fr]=Afficheur de polices
+GenericName[fy]=Lettertypewerjefte
+GenericName[ga]=Amharcán Clófhoirne
+GenericName[gl]=Visor de Fontes
+GenericName[he]=מציג גופנים
+GenericName[hr]=Preglednik fontova
+GenericName[hu]=Betűtípusböngésző
+GenericName[id]=Penampil Font
+GenericName[is]=Leturskoðari
+GenericName[it]=Visualizzatore di caratteri
+GenericName[ja]=フォントビューア
+GenericName[ka]=პროგრამა ფონტების სანახავად
+GenericName[kk]=Қаріпті қарап-шығу
+GenericName[km]=កម្មវិធី​មើល​ពុម្ពអក្សរ
+GenericName[ko]=글꼴 뷰어
+GenericName[lt]=Šriftų žiūryklė
+GenericName[lv]=Fontu Skatītājs
+GenericName[mk]=Прегледувач на фонтови
+GenericName[ms]=Pemapar Fon
+GenericName[mt]=Werrej tal-fonts
+GenericName[nb]=Skrifttypeviser
+GenericName[nds]=Schriftoortkieker
+GenericName[ne]=फन्ट दर्शक
+GenericName[nl]=Lettertypeweergave
+GenericName[nn]=Skriftvisar
+GenericName[pa]=ਫੋਂਟ ਦਰਸ਼ਕ
+GenericName[pl]=Przeglądarka czcionek
+GenericName[pt]=Visualizador de Tipos de Letra
+GenericName[pt_BR]=Visualizador de fontes
+GenericName[ro]=Vizualizor de fonturi
+GenericName[ru]=Программа просмотра шрифтов
+GenericName[rw]=Ikigaragaza Imyandikire
+GenericName[se]=Fontačájeheaddji
+GenericName[sk]=Prehliadač písiem
+GenericName[sl]=Pregledovalnik pisav
+GenericName[sr]=Приказивач фонтова
+GenericName[sr@Latn]=Prikazivač fontova
+GenericName[sv]=Teckensnittsvisning
+GenericName[tg]=Намоишгари ҳарфҳо
+GenericName[th]=โปรแกรมดูแบบอักษร
+GenericName[tr]=Yazıtipi Görüntüleyici
+GenericName[tt]=Yazu Kürsätkeç
+GenericName[uk]=Переглядач шрифтів
+GenericName[uz]=Shrift koʻruvchi
+GenericName[uz@cyrillic]=Шрифт кўрувчи
+GenericName[vi]=Trình xem Phông chữ
+GenericName[wa]=Håyneu di fontes
+GenericName[zh_CN]=字体查看器
+GenericName[zh_TW]=字型檢視器
+Terminal=false
+InitialPreference=1
+Categories=Qt;KDE;Utility;X-KDE-More;
diff --git a/kcontrol/kfontinst/viewpart/kfontviewpart.desktop b/kcontrol/kfontinst/viewpart/kfontviewpart.desktop
new file mode 100644
index 000000000..e1bcd6933
--- /dev/null
+++ b/kcontrol/kfontinst/viewpart/kfontviewpart.desktop
@@ -0,0 +1,86 @@
+[Desktop Entry]
+Name=Font Viewer
+Name[af]=Skriftipe Besigter
+Name[ar]=معاين المحرف
+Name[az]=Yazı Növü Nümayişçisi
+Name[be]=Праглядальнік шрыфтоў
+Name[bg]=Преглед на шрифт
+Name[bn]=ফন্ট প্রদর্শক
+Name[br]=Gweler Nodrezhoù
+Name[bs]=Preglednik fontova
+Name[ca]=Visor de lletres
+Name[cs]=Prohlížeč písem
+Name[csb]=Przezérnik fòntów
+Name[cy]=Gwelydd Ffont
+Name[da]=Skrifttypevisning
+Name[de]=Schriftartenbetrachter
+Name[el]=Προβολέας γραμματοσειρών
+Name[eo]=Tiparorigardilo
+Name[es]=Visor de tipos de letra
+Name[et]=Fontide vaataja
+Name[eu]=Letra-tipo ikustailea
+Name[fa]=مشاهده‌گر قلم
+Name[fi]=Kirjasinten näytin
+Name[fr]=Afficheur de polices
+Name[fy]=Lettertypewerjefteprogramma
+Name[ga]=Amharcán Clófhoirne
+Name[gl]=Visor de Fontes
+Name[he]=מציג גופנים
+Name[hi]=फ़ॉन्ट प्रदर्शक
+Name[hr]=Preglednik fontova
+Name[hu]=A betűtípusok áttekintése
+Name[id]=Penampil Font
+Name[is]=Leturskoðari
+Name[it]=Vista caratteri
+Name[ja]=フォントビューア
+Name[ka]=პროგრამა ფონტების სანახავად
+Name[kk]=Қаріпті қарап-шығу
+Name[km]=កម្មវិធី​មើល​ពុម្ពអក្សរ
+Name[ko]=글꼴 뷰어
+Name[lo]=ມຸມມອງແບບໄອຄອນ
+Name[lt]=Šrifto žiūriklis
+Name[lv]=Fontu Skatītājs
+Name[mk]=Прегледувач на фонтови
+Name[mn]=Бичиг харагч
+Name[ms]=Pemapar Fon
+Name[mt]=Werrej tal-fonts
+Name[nb]=Skrifttypeviser
+Name[nds]=Schriftoortkieker
+Name[ne]=फन्ट दर्शक
+Name[nl]=Lettertypeweergaveprogramma
+Name[nn]=Skriftvisar
+Name[nso]=Molebeledi wa Fonto
+Name[pa]=ਫੋਂਟ ਦਰਸ਼ਕ
+Name[pl]=Przeglądarka czcionek
+Name[pt]=Visualizador do Tipo de Letra
+Name[pt_BR]=Visualizador de Fontes
+Name[ro]=Vizualizor de fonturi
+Name[ru]=Просмотр шрифтов
+Name[rw]=Ikigaragaza Imyandikire
+Name[se]=Fontačájeheaddji
+Name[sk]=Prehliadač písiem
+Name[sl]=Prikazovalnik pisav
+Name[sr]=Приказивач фонтова
+Name[sr@Latn]=Prikazivač fontova
+Name[sv]=Teckensnittsvisning
+Name[ta]=எழுத்துரு காட்சி
+Name[tg]=Намоишгари ҳарф
+Name[th]=โปรแกรมดูแบบอักษร
+Name[tr]=Yazıtipi İzleyici
+Name[tt]=Yazu Kürsätkeç
+Name[uk]=Переглядач шрифтів
+Name[uz]=Shrift koʻruvchi
+Name[uz@cyrillic]=Шрифт кўрувчи
+Name[ven]=Muvhoni wa Fontu
+Name[vi]=Trình xem Phông chữ
+Name[wa]=Håyneu di fontes
+Name[xh]=Imboniselo Yohlobo lwegama
+Name[zh_CN]=字体查看器
+Name[zh_TW]=字型檢視器
+Name[zu]=Umbukisi Wohlobo lwamagama
+MimeType=application/x-font-ttf;application/x-font-type1;application/x-font-otf;application/x-font-ttc;application/x-font-pcf;application/x-font-bdf;fonts/package
+ServiceTypes=KParts/ReadOnlyPart,Browser/View
+X-KDE-Library=libkfontviewpart
+Type=Service
+InitialPreference=1
+Icon=fonts
diff --git a/kcontrol/kfontinst/viewpart/kfontviewpart.rc b/kcontrol/kfontinst/viewpart/kfontviewpart.rc
new file mode 100644
index 000000000..5df54a47c
--- /dev/null
+++ b/kcontrol/kfontinst/viewpart/kfontviewpart.rc
@@ -0,0 +1,9 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="kfontviewpart" version="1">
+<ToolBar name="mainToolBar">
+ <text>&amp;Main Toolbar</text>
+ <Action name="print"/>
+ <Action name="changeText"/>
+</ToolBar>
+</kpartgui>
+
diff --git a/kcontrol/kfontinst/viewpart/kfontviewui.rc b/kcontrol/kfontinst/viewpart/kfontviewui.rc
new file mode 100644
index 000000000..f2e4a86fa
--- /dev/null
+++ b/kcontrol/kfontinst/viewpart/kfontviewui.rc
@@ -0,0 +1,4 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="kfontviewui" version="1">
+</kpartgui>
+