diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | 4aed2c8219774f5d797760606b8489a92ddc5163 (patch) | |
tree | 3f8c130f7d269626bf6a9447407ef6c35954426a /kcontrol/kfontinst | |
download | tdebase-4aed2c8219774f5d797760606b8489a92ddc5163.tar.gz tdebase-4aed2c8219774f5d797760606b8489a92ddc5163.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdebase@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kcontrol/kfontinst')
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 Binary files differnew file mode 100644 index 000000000..61eef357e --- /dev/null +++ b/kcontrol/kfontinst/kcmfontinst/cr16-action-newfont.png diff --git a/kcontrol/kfontinst/kcmfontinst/cr22-action-newfont.png b/kcontrol/kfontinst/kcmfontinst/cr22-action-newfont.png Binary files differnew file mode 100644 index 000000000..049197a35 --- /dev/null +++ b/kcontrol/kfontinst/kcmfontinst/cr22-action-newfont.png diff --git a/kcontrol/kfontinst/kcmfontinst/cr32-action-newfont.png b/kcontrol/kfontinst/kcmfontinst/cr32-action-newfont.png Binary files differnew file mode 100644 index 000000000..9cd3d57bc --- /dev/null +++ b/kcontrol/kfontinst/kcmfontinst/cr32-action-newfont.png 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(¤t, 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 §) +{ + return i18n(KFI_KIO_FONTS_SYS)==sect || KFI_KIO_FONTS_SYS==sect; +} + +inline bool isUserFolder(const QString §) +{ + 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>&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> + |