src/gui/image/qxpmhandler.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "private/qxpmhandler_p.h"
       
    43 
       
    44 #ifndef QT_NO_IMAGEFORMAT_XPM
       
    45 
       
    46 #include <private/qcolor_p.h>
       
    47 #include <qimage.h>
       
    48 #include <qmap.h>
       
    49 #include <qtextstream.h>
       
    50 #include <qvariant.h>
       
    51 
       
    52 #if defined(Q_CC_BOR)
       
    53 // needed for qsort() because of a std namespace problem on Borland
       
    54 #include "qplatformdefs.h"
       
    55 #endif
       
    56 
       
    57 #include <stdlib.h>
       
    58 
       
    59 #if defined(Q_OS_WINCE)
       
    60 #include "qguifunctions_wince.h"
       
    61 #endif
       
    62 
       
    63 QT_BEGIN_NAMESPACE
       
    64 
       
    65 static quint64 xpmHash(const QString &str)
       
    66 {
       
    67     unsigned int hashValue = 0;
       
    68     for (int i = 0; i < str.size(); ++i) {
       
    69         hashValue <<= 8;
       
    70         hashValue += (unsigned int)str.at(i).unicode();
       
    71     }
       
    72     return hashValue;
       
    73 }
       
    74 static quint64 xpmHash(char *str)
       
    75 {
       
    76     unsigned int hashValue = 0;
       
    77     while (*str != '\0') {
       
    78         hashValue <<= 8;
       
    79         hashValue += (unsigned int)*str;
       
    80         ++str;
       
    81     }
       
    82     return hashValue;
       
    83 }
       
    84 
       
    85 #ifdef QRGB
       
    86 #undef QRGB
       
    87 #endif
       
    88 #define QRGB(r,g,b) (r*65536 + g*256 + b)
       
    89 
       
    90 static const int xpmRgbTblSize = 657;
       
    91 
       
    92 static const struct XPMRGBData {
       
    93     uint  value;
       
    94     const char *name;
       
    95 } xpmRgbTbl[] = {
       
    96   { QRGB(240,248,255),  "aliceblue" },
       
    97   { QRGB(250,235,215),  "antiquewhite" },
       
    98   { QRGB(255,239,219),  "antiquewhite1" },
       
    99   { QRGB(238,223,204),  "antiquewhite2" },
       
   100   { QRGB(205,192,176),  "antiquewhite3" },
       
   101   { QRGB(139,131,120),  "antiquewhite4" },
       
   102   { QRGB(127,255,212),  "aquamarine" },
       
   103   { QRGB(127,255,212),  "aquamarine1" },
       
   104   { QRGB(118,238,198),  "aquamarine2" },
       
   105   { QRGB(102,205,170),  "aquamarine3" },
       
   106   { QRGB( 69,139,116),  "aquamarine4" },
       
   107   { QRGB(240,255,255),  "azure" },
       
   108   { QRGB(240,255,255),  "azure1" },
       
   109   { QRGB(224,238,238),  "azure2" },
       
   110   { QRGB(193,205,205),  "azure3" },
       
   111   { QRGB(131,139,139),  "azure4" },
       
   112   { QRGB(245,245,220),  "beige" },
       
   113   { QRGB(255,228,196),  "bisque" },
       
   114   { QRGB(255,228,196),  "bisque1" },
       
   115   { QRGB(238,213,183),  "bisque2" },
       
   116   { QRGB(205,183,158),  "bisque3" },
       
   117   { QRGB(139,125,107),  "bisque4" },
       
   118   { QRGB(  0,  0,  0),  "black" },
       
   119   { QRGB(255,235,205),  "blanchedalmond" },
       
   120   { QRGB(  0,  0,255),  "blue" },
       
   121   { QRGB(  0,  0,255),  "blue1" },
       
   122   { QRGB(  0,  0,238),  "blue2" },
       
   123   { QRGB(  0,  0,205),  "blue3" },
       
   124   { QRGB(  0,  0,139),  "blue4" },
       
   125   { QRGB(138, 43,226),  "blueviolet" },
       
   126   { QRGB(165, 42, 42),  "brown" },
       
   127   { QRGB(255, 64, 64),  "brown1" },
       
   128   { QRGB(238, 59, 59),  "brown2" },
       
   129   { QRGB(205, 51, 51),  "brown3" },
       
   130   { QRGB(139, 35, 35),  "brown4" },
       
   131   { QRGB(222,184,135),  "burlywood" },
       
   132   { QRGB(255,211,155),  "burlywood1" },
       
   133   { QRGB(238,197,145),  "burlywood2" },
       
   134   { QRGB(205,170,125),  "burlywood3" },
       
   135   { QRGB(139,115, 85),  "burlywood4" },
       
   136   { QRGB( 95,158,160),  "cadetblue" },
       
   137   { QRGB(152,245,255),  "cadetblue1" },
       
   138   { QRGB(142,229,238),  "cadetblue2" },
       
   139   { QRGB(122,197,205),  "cadetblue3" },
       
   140   { QRGB( 83,134,139),  "cadetblue4" },
       
   141   { QRGB(127,255,  0),  "chartreuse" },
       
   142   { QRGB(127,255,  0),  "chartreuse1" },
       
   143   { QRGB(118,238,  0),  "chartreuse2" },
       
   144   { QRGB(102,205,  0),  "chartreuse3" },
       
   145   { QRGB( 69,139,  0),  "chartreuse4" },
       
   146   { QRGB(210,105, 30),  "chocolate" },
       
   147   { QRGB(255,127, 36),  "chocolate1" },
       
   148   { QRGB(238,118, 33),  "chocolate2" },
       
   149   { QRGB(205,102, 29),  "chocolate3" },
       
   150   { QRGB(139, 69, 19),  "chocolate4" },
       
   151   { QRGB(255,127, 80),  "coral" },
       
   152   { QRGB(255,114, 86),  "coral1" },
       
   153   { QRGB(238,106, 80),  "coral2" },
       
   154   { QRGB(205, 91, 69),  "coral3" },
       
   155   { QRGB(139, 62, 47),  "coral4" },
       
   156   { QRGB(100,149,237),  "cornflowerblue" },
       
   157   { QRGB(255,248,220),  "cornsilk" },
       
   158   { QRGB(255,248,220),  "cornsilk1" },
       
   159   { QRGB(238,232,205),  "cornsilk2" },
       
   160   { QRGB(205,200,177),  "cornsilk3" },
       
   161   { QRGB(139,136,120),  "cornsilk4" },
       
   162   { QRGB(  0,255,255),  "cyan" },
       
   163   { QRGB(  0,255,255),  "cyan1" },
       
   164   { QRGB(  0,238,238),  "cyan2" },
       
   165   { QRGB(  0,205,205),  "cyan3" },
       
   166   { QRGB(  0,139,139),  "cyan4" },
       
   167   { QRGB(  0,  0,139),  "darkblue" },
       
   168   { QRGB(  0,139,139),  "darkcyan" },
       
   169   { QRGB(184,134, 11),  "darkgoldenrod" },
       
   170   { QRGB(255,185, 15),  "darkgoldenrod1" },
       
   171   { QRGB(238,173, 14),  "darkgoldenrod2" },
       
   172   { QRGB(205,149, 12),  "darkgoldenrod3" },
       
   173   { QRGB(139,101,  8),  "darkgoldenrod4" },
       
   174   { QRGB(169,169,169),  "darkgray" },
       
   175   { QRGB(  0,100,  0),  "darkgreen" },
       
   176   { QRGB(169,169,169),  "darkgrey" },
       
   177   { QRGB(189,183,107),  "darkkhaki" },
       
   178   { QRGB(139,  0,139),  "darkmagenta" },
       
   179   { QRGB( 85,107, 47),  "darkolivegreen" },
       
   180   { QRGB(202,255,112),  "darkolivegreen1" },
       
   181   { QRGB(188,238,104),  "darkolivegreen2" },
       
   182   { QRGB(162,205, 90),  "darkolivegreen3" },
       
   183   { QRGB(110,139, 61),  "darkolivegreen4" },
       
   184   { QRGB(255,140,  0),  "darkorange" },
       
   185   { QRGB(255,127,  0),  "darkorange1" },
       
   186   { QRGB(238,118,  0),  "darkorange2" },
       
   187   { QRGB(205,102,  0),  "darkorange3" },
       
   188   { QRGB(139, 69,  0),  "darkorange4" },
       
   189   { QRGB(153, 50,204),  "darkorchid" },
       
   190   { QRGB(191, 62,255),  "darkorchid1" },
       
   191   { QRGB(178, 58,238),  "darkorchid2" },
       
   192   { QRGB(154, 50,205),  "darkorchid3" },
       
   193   { QRGB(104, 34,139),  "darkorchid4" },
       
   194   { QRGB(139,  0,  0),  "darkred" },
       
   195   { QRGB(233,150,122),  "darksalmon" },
       
   196   { QRGB(143,188,143),  "darkseagreen" },
       
   197   { QRGB(193,255,193),  "darkseagreen1" },
       
   198   { QRGB(180,238,180),  "darkseagreen2" },
       
   199   { QRGB(155,205,155),  "darkseagreen3" },
       
   200   { QRGB(105,139,105),  "darkseagreen4" },
       
   201   { QRGB( 72, 61,139),  "darkslateblue" },
       
   202   { QRGB( 47, 79, 79),  "darkslategray" },
       
   203   { QRGB(151,255,255),  "darkslategray1" },
       
   204   { QRGB(141,238,238),  "darkslategray2" },
       
   205   { QRGB(121,205,205),  "darkslategray3" },
       
   206   { QRGB( 82,139,139),  "darkslategray4" },
       
   207   { QRGB( 47, 79, 79),  "darkslategrey" },
       
   208   { QRGB(  0,206,209),  "darkturquoise" },
       
   209   { QRGB(148,  0,211),  "darkviolet" },
       
   210   { QRGB(255, 20,147),  "deeppink" },
       
   211   { QRGB(255, 20,147),  "deeppink1" },
       
   212   { QRGB(238, 18,137),  "deeppink2" },
       
   213   { QRGB(205, 16,118),  "deeppink3" },
       
   214   { QRGB(139, 10, 80),  "deeppink4" },
       
   215   { QRGB(  0,191,255),  "deepskyblue" },
       
   216   { QRGB(  0,191,255),  "deepskyblue1" },
       
   217   { QRGB(  0,178,238),  "deepskyblue2" },
       
   218   { QRGB(  0,154,205),  "deepskyblue3" },
       
   219   { QRGB(  0,104,139),  "deepskyblue4" },
       
   220   { QRGB(105,105,105),  "dimgray" },
       
   221   { QRGB(105,105,105),  "dimgrey" },
       
   222   { QRGB( 30,144,255),  "dodgerblue" },
       
   223   { QRGB( 30,144,255),  "dodgerblue1" },
       
   224   { QRGB( 28,134,238),  "dodgerblue2" },
       
   225   { QRGB( 24,116,205),  "dodgerblue3" },
       
   226   { QRGB( 16, 78,139),  "dodgerblue4" },
       
   227   { QRGB(178, 34, 34),  "firebrick" },
       
   228   { QRGB(255, 48, 48),  "firebrick1" },
       
   229   { QRGB(238, 44, 44),  "firebrick2" },
       
   230   { QRGB(205, 38, 38),  "firebrick3" },
       
   231   { QRGB(139, 26, 26),  "firebrick4" },
       
   232   { QRGB(255,250,240),  "floralwhite" },
       
   233   { QRGB( 34,139, 34),  "forestgreen" },
       
   234   { QRGB(220,220,220),  "gainsboro" },
       
   235   { QRGB(248,248,255),  "ghostwhite" },
       
   236   { QRGB(255,215,  0),  "gold" },
       
   237   { QRGB(255,215,  0),  "gold1" },
       
   238   { QRGB(238,201,  0),  "gold2" },
       
   239   { QRGB(205,173,  0),  "gold3" },
       
   240   { QRGB(139,117,  0),  "gold4" },
       
   241   { QRGB(218,165, 32),  "goldenrod" },
       
   242   { QRGB(255,193, 37),  "goldenrod1" },
       
   243   { QRGB(238,180, 34),  "goldenrod2" },
       
   244   { QRGB(205,155, 29),  "goldenrod3" },
       
   245   { QRGB(139,105, 20),  "goldenrod4" },
       
   246   { QRGB(190,190,190),  "gray" },
       
   247   { QRGB(  0,  0,  0),  "gray0" },
       
   248   { QRGB(  3,  3,  3),  "gray1" },
       
   249   { QRGB( 26, 26, 26),  "gray10" },
       
   250   { QRGB(255,255,255),  "gray100" },
       
   251   { QRGB( 28, 28, 28),  "gray11" },
       
   252   { QRGB( 31, 31, 31),  "gray12" },
       
   253   { QRGB( 33, 33, 33),  "gray13" },
       
   254   { QRGB( 36, 36, 36),  "gray14" },
       
   255   { QRGB( 38, 38, 38),  "gray15" },
       
   256   { QRGB( 41, 41, 41),  "gray16" },
       
   257   { QRGB( 43, 43, 43),  "gray17" },
       
   258   { QRGB( 46, 46, 46),  "gray18" },
       
   259   { QRGB( 48, 48, 48),  "gray19" },
       
   260   { QRGB(  5,  5,  5),  "gray2" },
       
   261   { QRGB( 51, 51, 51),  "gray20" },
       
   262   { QRGB( 54, 54, 54),  "gray21" },
       
   263   { QRGB( 56, 56, 56),  "gray22" },
       
   264   { QRGB( 59, 59, 59),  "gray23" },
       
   265   { QRGB( 61, 61, 61),  "gray24" },
       
   266   { QRGB( 64, 64, 64),  "gray25" },
       
   267   { QRGB( 66, 66, 66),  "gray26" },
       
   268   { QRGB( 69, 69, 69),  "gray27" },
       
   269   { QRGB( 71, 71, 71),  "gray28" },
       
   270   { QRGB( 74, 74, 74),  "gray29" },
       
   271   { QRGB(  8,  8,  8),  "gray3" },
       
   272   { QRGB( 77, 77, 77),  "gray30" },
       
   273   { QRGB( 79, 79, 79),  "gray31" },
       
   274   { QRGB( 82, 82, 82),  "gray32" },
       
   275   { QRGB( 84, 84, 84),  "gray33" },
       
   276   { QRGB( 87, 87, 87),  "gray34" },
       
   277   { QRGB( 89, 89, 89),  "gray35" },
       
   278   { QRGB( 92, 92, 92),  "gray36" },
       
   279   { QRGB( 94, 94, 94),  "gray37" },
       
   280   { QRGB( 97, 97, 97),  "gray38" },
       
   281   { QRGB( 99, 99, 99),  "gray39" },
       
   282   { QRGB( 10, 10, 10),  "gray4" },
       
   283   { QRGB(102,102,102),  "gray40" },
       
   284   { QRGB(105,105,105),  "gray41" },
       
   285   { QRGB(107,107,107),  "gray42" },
       
   286   { QRGB(110,110,110),  "gray43" },
       
   287   { QRGB(112,112,112),  "gray44" },
       
   288   { QRGB(115,115,115),  "gray45" },
       
   289   { QRGB(117,117,117),  "gray46" },
       
   290   { QRGB(120,120,120),  "gray47" },
       
   291   { QRGB(122,122,122),  "gray48" },
       
   292   { QRGB(125,125,125),  "gray49" },
       
   293   { QRGB( 13, 13, 13),  "gray5" },
       
   294   { QRGB(127,127,127),  "gray50" },
       
   295   { QRGB(130,130,130),  "gray51" },
       
   296   { QRGB(133,133,133),  "gray52" },
       
   297   { QRGB(135,135,135),  "gray53" },
       
   298   { QRGB(138,138,138),  "gray54" },
       
   299   { QRGB(140,140,140),  "gray55" },
       
   300   { QRGB(143,143,143),  "gray56" },
       
   301   { QRGB(145,145,145),  "gray57" },
       
   302   { QRGB(148,148,148),  "gray58" },
       
   303   { QRGB(150,150,150),  "gray59" },
       
   304   { QRGB( 15, 15, 15),  "gray6" },
       
   305   { QRGB(153,153,153),  "gray60" },
       
   306   { QRGB(156,156,156),  "gray61" },
       
   307   { QRGB(158,158,158),  "gray62" },
       
   308   { QRGB(161,161,161),  "gray63" },
       
   309   { QRGB(163,163,163),  "gray64" },
       
   310   { QRGB(166,166,166),  "gray65" },
       
   311   { QRGB(168,168,168),  "gray66" },
       
   312   { QRGB(171,171,171),  "gray67" },
       
   313   { QRGB(173,173,173),  "gray68" },
       
   314   { QRGB(176,176,176),  "gray69" },
       
   315   { QRGB( 18, 18, 18),  "gray7" },
       
   316   { QRGB(179,179,179),  "gray70" },
       
   317   { QRGB(181,181,181),  "gray71" },
       
   318   { QRGB(184,184,184),  "gray72" },
       
   319   { QRGB(186,186,186),  "gray73" },
       
   320   { QRGB(189,189,189),  "gray74" },
       
   321   { QRGB(191,191,191),  "gray75" },
       
   322   { QRGB(194,194,194),  "gray76" },
       
   323   { QRGB(196,196,196),  "gray77" },
       
   324   { QRGB(199,199,199),  "gray78" },
       
   325   { QRGB(201,201,201),  "gray79" },
       
   326   { QRGB( 20, 20, 20),  "gray8" },
       
   327   { QRGB(204,204,204),  "gray80" },
       
   328   { QRGB(207,207,207),  "gray81" },
       
   329   { QRGB(209,209,209),  "gray82" },
       
   330   { QRGB(212,212,212),  "gray83" },
       
   331   { QRGB(214,214,214),  "gray84" },
       
   332   { QRGB(217,217,217),  "gray85" },
       
   333   { QRGB(219,219,219),  "gray86" },
       
   334   { QRGB(222,222,222),  "gray87" },
       
   335   { QRGB(224,224,224),  "gray88" },
       
   336   { QRGB(227,227,227),  "gray89" },
       
   337   { QRGB( 23, 23, 23),  "gray9" },
       
   338   { QRGB(229,229,229),  "gray90" },
       
   339   { QRGB(232,232,232),  "gray91" },
       
   340   { QRGB(235,235,235),  "gray92" },
       
   341   { QRGB(237,237,237),  "gray93" },
       
   342   { QRGB(240,240,240),  "gray94" },
       
   343   { QRGB(242,242,242),  "gray95" },
       
   344   { QRGB(245,245,245),  "gray96" },
       
   345   { QRGB(247,247,247),  "gray97" },
       
   346   { QRGB(250,250,250),  "gray98" },
       
   347   { QRGB(252,252,252),  "gray99" },
       
   348   { QRGB(  0,255,  0),  "green" },
       
   349   { QRGB(  0,255,  0),  "green1" },
       
   350   { QRGB(  0,238,  0),  "green2" },
       
   351   { QRGB(  0,205,  0),  "green3" },
       
   352   { QRGB(  0,139,  0),  "green4" },
       
   353   { QRGB(173,255, 47),  "greenyellow" },
       
   354   { QRGB(190,190,190),  "grey" },
       
   355   { QRGB(  0,  0,  0),  "grey0" },
       
   356   { QRGB(  3,  3,  3),  "grey1" },
       
   357   { QRGB( 26, 26, 26),  "grey10" },
       
   358   { QRGB(255,255,255),  "grey100" },
       
   359   { QRGB( 28, 28, 28),  "grey11" },
       
   360   { QRGB( 31, 31, 31),  "grey12" },
       
   361   { QRGB( 33, 33, 33),  "grey13" },
       
   362   { QRGB( 36, 36, 36),  "grey14" },
       
   363   { QRGB( 38, 38, 38),  "grey15" },
       
   364   { QRGB( 41, 41, 41),  "grey16" },
       
   365   { QRGB( 43, 43, 43),  "grey17" },
       
   366   { QRGB( 46, 46, 46),  "grey18" },
       
   367   { QRGB( 48, 48, 48),  "grey19" },
       
   368   { QRGB(  5,  5,  5),  "grey2" },
       
   369   { QRGB( 51, 51, 51),  "grey20" },
       
   370   { QRGB( 54, 54, 54),  "grey21" },
       
   371   { QRGB( 56, 56, 56),  "grey22" },
       
   372   { QRGB( 59, 59, 59),  "grey23" },
       
   373   { QRGB( 61, 61, 61),  "grey24" },
       
   374   { QRGB( 64, 64, 64),  "grey25" },
       
   375   { QRGB( 66, 66, 66),  "grey26" },
       
   376   { QRGB( 69, 69, 69),  "grey27" },
       
   377   { QRGB( 71, 71, 71),  "grey28" },
       
   378   { QRGB( 74, 74, 74),  "grey29" },
       
   379   { QRGB(  8,  8,  8),  "grey3" },
       
   380   { QRGB( 77, 77, 77),  "grey30" },
       
   381   { QRGB( 79, 79, 79),  "grey31" },
       
   382   { QRGB( 82, 82, 82),  "grey32" },
       
   383   { QRGB( 84, 84, 84),  "grey33" },
       
   384   { QRGB( 87, 87, 87),  "grey34" },
       
   385   { QRGB( 89, 89, 89),  "grey35" },
       
   386   { QRGB( 92, 92, 92),  "grey36" },
       
   387   { QRGB( 94, 94, 94),  "grey37" },
       
   388   { QRGB( 97, 97, 97),  "grey38" },
       
   389   { QRGB( 99, 99, 99),  "grey39" },
       
   390   { QRGB( 10, 10, 10),  "grey4" },
       
   391   { QRGB(102,102,102),  "grey40" },
       
   392   { QRGB(105,105,105),  "grey41" },
       
   393   { QRGB(107,107,107),  "grey42" },
       
   394   { QRGB(110,110,110),  "grey43" },
       
   395   { QRGB(112,112,112),  "grey44" },
       
   396   { QRGB(115,115,115),  "grey45" },
       
   397   { QRGB(117,117,117),  "grey46" },
       
   398   { QRGB(120,120,120),  "grey47" },
       
   399   { QRGB(122,122,122),  "grey48" },
       
   400   { QRGB(125,125,125),  "grey49" },
       
   401   { QRGB( 13, 13, 13),  "grey5" },
       
   402   { QRGB(127,127,127),  "grey50" },
       
   403   { QRGB(130,130,130),  "grey51" },
       
   404   { QRGB(133,133,133),  "grey52" },
       
   405   { QRGB(135,135,135),  "grey53" },
       
   406   { QRGB(138,138,138),  "grey54" },
       
   407   { QRGB(140,140,140),  "grey55" },
       
   408   { QRGB(143,143,143),  "grey56" },
       
   409   { QRGB(145,145,145),  "grey57" },
       
   410   { QRGB(148,148,148),  "grey58" },
       
   411   { QRGB(150,150,150),  "grey59" },
       
   412   { QRGB( 15, 15, 15),  "grey6" },
       
   413   { QRGB(153,153,153),  "grey60" },
       
   414   { QRGB(156,156,156),  "grey61" },
       
   415   { QRGB(158,158,158),  "grey62" },
       
   416   { QRGB(161,161,161),  "grey63" },
       
   417   { QRGB(163,163,163),  "grey64" },
       
   418   { QRGB(166,166,166),  "grey65" },
       
   419   { QRGB(168,168,168),  "grey66" },
       
   420   { QRGB(171,171,171),  "grey67" },
       
   421   { QRGB(173,173,173),  "grey68" },
       
   422   { QRGB(176,176,176),  "grey69" },
       
   423   { QRGB( 18, 18, 18),  "grey7" },
       
   424   { QRGB(179,179,179),  "grey70" },
       
   425   { QRGB(181,181,181),  "grey71" },
       
   426   { QRGB(184,184,184),  "grey72" },
       
   427   { QRGB(186,186,186),  "grey73" },
       
   428   { QRGB(189,189,189),  "grey74" },
       
   429   { QRGB(191,191,191),  "grey75" },
       
   430   { QRGB(194,194,194),  "grey76" },
       
   431   { QRGB(196,196,196),  "grey77" },
       
   432   { QRGB(199,199,199),  "grey78" },
       
   433   { QRGB(201,201,201),  "grey79" },
       
   434   { QRGB( 20, 20, 20),  "grey8" },
       
   435   { QRGB(204,204,204),  "grey80" },
       
   436   { QRGB(207,207,207),  "grey81" },
       
   437   { QRGB(209,209,209),  "grey82" },
       
   438   { QRGB(212,212,212),  "grey83" },
       
   439   { QRGB(214,214,214),  "grey84" },
       
   440   { QRGB(217,217,217),  "grey85" },
       
   441   { QRGB(219,219,219),  "grey86" },
       
   442   { QRGB(222,222,222),  "grey87" },
       
   443   { QRGB(224,224,224),  "grey88" },
       
   444   { QRGB(227,227,227),  "grey89" },
       
   445   { QRGB( 23, 23, 23),  "grey9" },
       
   446   { QRGB(229,229,229),  "grey90" },
       
   447   { QRGB(232,232,232),  "grey91" },
       
   448   { QRGB(235,235,235),  "grey92" },
       
   449   { QRGB(237,237,237),  "grey93" },
       
   450   { QRGB(240,240,240),  "grey94" },
       
   451   { QRGB(242,242,242),  "grey95" },
       
   452   { QRGB(245,245,245),  "grey96" },
       
   453   { QRGB(247,247,247),  "grey97" },
       
   454   { QRGB(250,250,250),  "grey98" },
       
   455   { QRGB(252,252,252),  "grey99" },
       
   456   { QRGB(240,255,240),  "honeydew" },
       
   457   { QRGB(240,255,240),  "honeydew1" },
       
   458   { QRGB(224,238,224),  "honeydew2" },
       
   459   { QRGB(193,205,193),  "honeydew3" },
       
   460   { QRGB(131,139,131),  "honeydew4" },
       
   461   { QRGB(255,105,180),  "hotpink" },
       
   462   { QRGB(255,110,180),  "hotpink1" },
       
   463   { QRGB(238,106,167),  "hotpink2" },
       
   464   { QRGB(205, 96,144),  "hotpink3" },
       
   465   { QRGB(139, 58, 98),  "hotpink4" },
       
   466   { QRGB(205, 92, 92),  "indianred" },
       
   467   { QRGB(255,106,106),  "indianred1" },
       
   468   { QRGB(238, 99, 99),  "indianred2" },
       
   469   { QRGB(205, 85, 85),  "indianred3" },
       
   470   { QRGB(139, 58, 58),  "indianred4" },
       
   471   { QRGB(255,255,240),  "ivory" },
       
   472   { QRGB(255,255,240),  "ivory1" },
       
   473   { QRGB(238,238,224),  "ivory2" },
       
   474   { QRGB(205,205,193),  "ivory3" },
       
   475   { QRGB(139,139,131),  "ivory4" },
       
   476   { QRGB(240,230,140),  "khaki" },
       
   477   { QRGB(255,246,143),  "khaki1" },
       
   478   { QRGB(238,230,133),  "khaki2" },
       
   479   { QRGB(205,198,115),  "khaki3" },
       
   480   { QRGB(139,134, 78),  "khaki4" },
       
   481   { QRGB(230,230,250),  "lavender" },
       
   482   { QRGB(255,240,245),  "lavenderblush" },
       
   483   { QRGB(255,240,245),  "lavenderblush1" },
       
   484   { QRGB(238,224,229),  "lavenderblush2" },
       
   485   { QRGB(205,193,197),  "lavenderblush3" },
       
   486   { QRGB(139,131,134),  "lavenderblush4" },
       
   487   { QRGB(124,252,  0),  "lawngreen" },
       
   488   { QRGB(255,250,205),  "lemonchiffon" },
       
   489   { QRGB(255,250,205),  "lemonchiffon1" },
       
   490   { QRGB(238,233,191),  "lemonchiffon2" },
       
   491   { QRGB(205,201,165),  "lemonchiffon3" },
       
   492   { QRGB(139,137,112),  "lemonchiffon4" },
       
   493   { QRGB(173,216,230),  "lightblue" },
       
   494   { QRGB(191,239,255),  "lightblue1" },
       
   495   { QRGB(178,223,238),  "lightblue2" },
       
   496   { QRGB(154,192,205),  "lightblue3" },
       
   497   { QRGB(104,131,139),  "lightblue4" },
       
   498   { QRGB(240,128,128),  "lightcoral" },
       
   499   { QRGB(224,255,255),  "lightcyan" },
       
   500   { QRGB(224,255,255),  "lightcyan1" },
       
   501   { QRGB(209,238,238),  "lightcyan2" },
       
   502   { QRGB(180,205,205),  "lightcyan3" },
       
   503   { QRGB(122,139,139),  "lightcyan4" },
       
   504   { QRGB(238,221,130),  "lightgoldenrod" },
       
   505   { QRGB(255,236,139),  "lightgoldenrod1" },
       
   506   { QRGB(238,220,130),  "lightgoldenrod2" },
       
   507   { QRGB(205,190,112),  "lightgoldenrod3" },
       
   508   { QRGB(139,129, 76),  "lightgoldenrod4" },
       
   509   { QRGB(250,250,210),  "lightgoldenrodyellow" },
       
   510   { QRGB(211,211,211),  "lightgray" },
       
   511   { QRGB(144,238,144),  "lightgreen" },
       
   512   { QRGB(211,211,211),  "lightgrey" },
       
   513   { QRGB(255,182,193),  "lightpink" },
       
   514   { QRGB(255,174,185),  "lightpink1" },
       
   515   { QRGB(238,162,173),  "lightpink2" },
       
   516   { QRGB(205,140,149),  "lightpink3" },
       
   517   { QRGB(139, 95,101),  "lightpink4" },
       
   518   { QRGB(255,160,122),  "lightsalmon" },
       
   519   { QRGB(255,160,122),  "lightsalmon1" },
       
   520   { QRGB(238,149,114),  "lightsalmon2" },
       
   521   { QRGB(205,129, 98),  "lightsalmon3" },
       
   522   { QRGB(139, 87, 66),  "lightsalmon4" },
       
   523   { QRGB( 32,178,170),  "lightseagreen" },
       
   524   { QRGB(135,206,250),  "lightskyblue" },
       
   525   { QRGB(176,226,255),  "lightskyblue1" },
       
   526   { QRGB(164,211,238),  "lightskyblue2" },
       
   527   { QRGB(141,182,205),  "lightskyblue3" },
       
   528   { QRGB( 96,123,139),  "lightskyblue4" },
       
   529   { QRGB(132,112,255),  "lightslateblue" },
       
   530   { QRGB(119,136,153),  "lightslategray" },
       
   531   { QRGB(119,136,153),  "lightslategrey" },
       
   532   { QRGB(176,196,222),  "lightsteelblue" },
       
   533   { QRGB(202,225,255),  "lightsteelblue1" },
       
   534   { QRGB(188,210,238),  "lightsteelblue2" },
       
   535   { QRGB(162,181,205),  "lightsteelblue3" },
       
   536   { QRGB(110,123,139),  "lightsteelblue4" },
       
   537   { QRGB(255,255,224),  "lightyellow" },
       
   538   { QRGB(255,255,224),  "lightyellow1" },
       
   539   { QRGB(238,238,209),  "lightyellow2" },
       
   540   { QRGB(205,205,180),  "lightyellow3" },
       
   541   { QRGB(139,139,122),  "lightyellow4" },
       
   542   { QRGB( 50,205, 50),  "limegreen" },
       
   543   { QRGB(250,240,230),  "linen" },
       
   544   { QRGB(255,  0,255),  "magenta" },
       
   545   { QRGB(255,  0,255),  "magenta1" },
       
   546   { QRGB(238,  0,238),  "magenta2" },
       
   547   { QRGB(205,  0,205),  "magenta3" },
       
   548   { QRGB(139,  0,139),  "magenta4" },
       
   549   { QRGB(176, 48, 96),  "maroon" },
       
   550   { QRGB(255, 52,179),  "maroon1" },
       
   551   { QRGB(238, 48,167),  "maroon2" },
       
   552   { QRGB(205, 41,144),  "maroon3" },
       
   553   { QRGB(139, 28, 98),  "maroon4" },
       
   554   { QRGB(102,205,170),  "mediumaquamarine" },
       
   555   { QRGB(  0,  0,205),  "mediumblue" },
       
   556   { QRGB(186, 85,211),  "mediumorchid" },
       
   557   { QRGB(224,102,255),  "mediumorchid1" },
       
   558   { QRGB(209, 95,238),  "mediumorchid2" },
       
   559   { QRGB(180, 82,205),  "mediumorchid3" },
       
   560   { QRGB(122, 55,139),  "mediumorchid4" },
       
   561   { QRGB(147,112,219),  "mediumpurple" },
       
   562   { QRGB(171,130,255),  "mediumpurple1" },
       
   563   { QRGB(159,121,238),  "mediumpurple2" },
       
   564   { QRGB(137,104,205),  "mediumpurple3" },
       
   565   { QRGB( 93, 71,139),  "mediumpurple4" },
       
   566   { QRGB( 60,179,113),  "mediumseagreen" },
       
   567   { QRGB(123,104,238),  "mediumslateblue" },
       
   568   { QRGB(  0,250,154),  "mediumspringgreen" },
       
   569   { QRGB( 72,209,204),  "mediumturquoise" },
       
   570   { QRGB(199, 21,133),  "mediumvioletred" },
       
   571   { QRGB( 25, 25,112),  "midnightblue" },
       
   572   { QRGB(245,255,250),  "mintcream" },
       
   573   { QRGB(255,228,225),  "mistyrose" },
       
   574   { QRGB(255,228,225),  "mistyrose1" },
       
   575   { QRGB(238,213,210),  "mistyrose2" },
       
   576   { QRGB(205,183,181),  "mistyrose3" },
       
   577   { QRGB(139,125,123),  "mistyrose4" },
       
   578   { QRGB(255,228,181),  "moccasin" },
       
   579   { QRGB(255,222,173),  "navajowhite" },
       
   580   { QRGB(255,222,173),  "navajowhite1" },
       
   581   { QRGB(238,207,161),  "navajowhite2" },
       
   582   { QRGB(205,179,139),  "navajowhite3" },
       
   583   { QRGB(139,121, 94),  "navajowhite4" },
       
   584   { QRGB(  0,  0,128),  "navy" },
       
   585   { QRGB(  0,  0,128),  "navyblue" },
       
   586   { QRGB(253,245,230),  "oldlace" },
       
   587   { QRGB(107,142, 35),  "olivedrab" },
       
   588   { QRGB(192,255, 62),  "olivedrab1" },
       
   589   { QRGB(179,238, 58),  "olivedrab2" },
       
   590   { QRGB(154,205, 50),  "olivedrab3" },
       
   591   { QRGB(105,139, 34),  "olivedrab4" },
       
   592   { QRGB(255,165,  0),  "orange" },
       
   593   { QRGB(255,165,  0),  "orange1" },
       
   594   { QRGB(238,154,  0),  "orange2" },
       
   595   { QRGB(205,133,  0),  "orange3" },
       
   596   { QRGB(139, 90,  0),  "orange4" },
       
   597   { QRGB(255, 69,  0),  "orangered" },
       
   598   { QRGB(255, 69,  0),  "orangered1" },
       
   599   { QRGB(238, 64,  0),  "orangered2" },
       
   600   { QRGB(205, 55,  0),  "orangered3" },
       
   601   { QRGB(139, 37,  0),  "orangered4" },
       
   602   { QRGB(218,112,214),  "orchid" },
       
   603   { QRGB(255,131,250),  "orchid1" },
       
   604   { QRGB(238,122,233),  "orchid2" },
       
   605   { QRGB(205,105,201),  "orchid3" },
       
   606   { QRGB(139, 71,137),  "orchid4" },
       
   607   { QRGB(238,232,170),  "palegoldenrod" },
       
   608   { QRGB(152,251,152),  "palegreen" },
       
   609   { QRGB(154,255,154),  "palegreen1" },
       
   610   { QRGB(144,238,144),  "palegreen2" },
       
   611   { QRGB(124,205,124),  "palegreen3" },
       
   612   { QRGB( 84,139, 84),  "palegreen4" },
       
   613   { QRGB(175,238,238),  "paleturquoise" },
       
   614   { QRGB(187,255,255),  "paleturquoise1" },
       
   615   { QRGB(174,238,238),  "paleturquoise2" },
       
   616   { QRGB(150,205,205),  "paleturquoise3" },
       
   617   { QRGB(102,139,139),  "paleturquoise4" },
       
   618   { QRGB(219,112,147),  "palevioletred" },
       
   619   { QRGB(255,130,171),  "palevioletred1" },
       
   620   { QRGB(238,121,159),  "palevioletred2" },
       
   621   { QRGB(205,104,137),  "palevioletred3" },
       
   622   { QRGB(139, 71, 93),  "palevioletred4" },
       
   623   { QRGB(255,239,213),  "papayawhip" },
       
   624   { QRGB(255,218,185),  "peachpuff" },
       
   625   { QRGB(255,218,185),  "peachpuff1" },
       
   626   { QRGB(238,203,173),  "peachpuff2" },
       
   627   { QRGB(205,175,149),  "peachpuff3" },
       
   628   { QRGB(139,119,101),  "peachpuff4" },
       
   629   { QRGB(205,133, 63),  "peru" },
       
   630   { QRGB(255,192,203),  "pink" },
       
   631   { QRGB(255,181,197),  "pink1" },
       
   632   { QRGB(238,169,184),  "pink2" },
       
   633   { QRGB(205,145,158),  "pink3" },
       
   634   { QRGB(139, 99,108),  "pink4" },
       
   635   { QRGB(221,160,221),  "plum" },
       
   636   { QRGB(255,187,255),  "plum1" },
       
   637   { QRGB(238,174,238),  "plum2" },
       
   638   { QRGB(205,150,205),  "plum3" },
       
   639   { QRGB(139,102,139),  "plum4" },
       
   640   { QRGB(176,224,230),  "powderblue" },
       
   641   { QRGB(160, 32,240),  "purple" },
       
   642   { QRGB(155, 48,255),  "purple1" },
       
   643   { QRGB(145, 44,238),  "purple2" },
       
   644   { QRGB(125, 38,205),  "purple3" },
       
   645   { QRGB( 85, 26,139),  "purple4" },
       
   646   { QRGB(255,  0,  0),  "red" },
       
   647   { QRGB(255,  0,  0),  "red1" },
       
   648   { QRGB(238,  0,  0),  "red2" },
       
   649   { QRGB(205,  0,  0),  "red3" },
       
   650   { QRGB(139,  0,  0),  "red4" },
       
   651   { QRGB(188,143,143),  "rosybrown" },
       
   652   { QRGB(255,193,193),  "rosybrown1" },
       
   653   { QRGB(238,180,180),  "rosybrown2" },
       
   654   { QRGB(205,155,155),  "rosybrown3" },
       
   655   { QRGB(139,105,105),  "rosybrown4" },
       
   656   { QRGB( 65,105,225),  "royalblue" },
       
   657   { QRGB( 72,118,255),  "royalblue1" },
       
   658   { QRGB( 67,110,238),  "royalblue2" },
       
   659   { QRGB( 58, 95,205),  "royalblue3" },
       
   660   { QRGB( 39, 64,139),  "royalblue4" },
       
   661   { QRGB(139, 69, 19),  "saddlebrown" },
       
   662   { QRGB(250,128,114),  "salmon" },
       
   663   { QRGB(255,140,105),  "salmon1" },
       
   664   { QRGB(238,130, 98),  "salmon2" },
       
   665   { QRGB(205,112, 84),  "salmon3" },
       
   666   { QRGB(139, 76, 57),  "salmon4" },
       
   667   { QRGB(244,164, 96),  "sandybrown" },
       
   668   { QRGB( 46,139, 87),  "seagreen" },
       
   669   { QRGB( 84,255,159),  "seagreen1" },
       
   670   { QRGB( 78,238,148),  "seagreen2" },
       
   671   { QRGB( 67,205,128),  "seagreen3" },
       
   672   { QRGB( 46,139, 87),  "seagreen4" },
       
   673   { QRGB(255,245,238),  "seashell" },
       
   674   { QRGB(255,245,238),  "seashell1" },
       
   675   { QRGB(238,229,222),  "seashell2" },
       
   676   { QRGB(205,197,191),  "seashell3" },
       
   677   { QRGB(139,134,130),  "seashell4" },
       
   678   { QRGB(160, 82, 45),  "sienna" },
       
   679   { QRGB(255,130, 71),  "sienna1" },
       
   680   { QRGB(238,121, 66),  "sienna2" },
       
   681   { QRGB(205,104, 57),  "sienna3" },
       
   682   { QRGB(139, 71, 38),  "sienna4" },
       
   683   { QRGB(135,206,235),  "skyblue" },
       
   684   { QRGB(135,206,255),  "skyblue1" },
       
   685   { QRGB(126,192,238),  "skyblue2" },
       
   686   { QRGB(108,166,205),  "skyblue3" },
       
   687   { QRGB( 74,112,139),  "skyblue4" },
       
   688   { QRGB(106, 90,205),  "slateblue" },
       
   689   { QRGB(131,111,255),  "slateblue1" },
       
   690   { QRGB(122,103,238),  "slateblue2" },
       
   691   { QRGB(105, 89,205),  "slateblue3" },
       
   692   { QRGB( 71, 60,139),  "slateblue4" },
       
   693   { QRGB(112,128,144),  "slategray" },
       
   694   { QRGB(198,226,255),  "slategray1" },
       
   695   { QRGB(185,211,238),  "slategray2" },
       
   696   { QRGB(159,182,205),  "slategray3" },
       
   697   { QRGB(108,123,139),  "slategray4" },
       
   698   { QRGB(112,128,144),  "slategrey" },
       
   699   { QRGB(255,250,250),  "snow" },
       
   700   { QRGB(255,250,250),  "snow1" },
       
   701   { QRGB(238,233,233),  "snow2" },
       
   702   { QRGB(205,201,201),  "snow3" },
       
   703   { QRGB(139,137,137),  "snow4" },
       
   704   { QRGB(  0,255,127),  "springgreen" },
       
   705   { QRGB(  0,255,127),  "springgreen1" },
       
   706   { QRGB(  0,238,118),  "springgreen2" },
       
   707   { QRGB(  0,205,102),  "springgreen3" },
       
   708   { QRGB(  0,139, 69),  "springgreen4" },
       
   709   { QRGB( 70,130,180),  "steelblue" },
       
   710   { QRGB( 99,184,255),  "steelblue1" },
       
   711   { QRGB( 92,172,238),  "steelblue2" },
       
   712   { QRGB( 79,148,205),  "steelblue3" },
       
   713   { QRGB( 54,100,139),  "steelblue4" },
       
   714   { QRGB(210,180,140),  "tan" },
       
   715   { QRGB(255,165, 79),  "tan1" },
       
   716   { QRGB(238,154, 73),  "tan2" },
       
   717   { QRGB(205,133, 63),  "tan3" },
       
   718   { QRGB(139, 90, 43),  "tan4" },
       
   719   { QRGB(216,191,216),  "thistle" },
       
   720   { QRGB(255,225,255),  "thistle1" },
       
   721   { QRGB(238,210,238),  "thistle2" },
       
   722   { QRGB(205,181,205),  "thistle3" },
       
   723   { QRGB(139,123,139),  "thistle4" },
       
   724   { QRGB(255, 99, 71),  "tomato" },
       
   725   { QRGB(255, 99, 71),  "tomato1" },
       
   726   { QRGB(238, 92, 66),  "tomato2" },
       
   727   { QRGB(205, 79, 57),  "tomato3" },
       
   728   { QRGB(139, 54, 38),  "tomato4" },
       
   729   { QRGB( 64,224,208),  "turquoise" },
       
   730   { QRGB(  0,245,255),  "turquoise1" },
       
   731   { QRGB(  0,229,238),  "turquoise2" },
       
   732   { QRGB(  0,197,205),  "turquoise3" },
       
   733   { QRGB(  0,134,139),  "turquoise4" },
       
   734   { QRGB(238,130,238),  "violet" },
       
   735   { QRGB(208, 32,144),  "violetred" },
       
   736   { QRGB(255, 62,150),  "violetred1" },
       
   737   { QRGB(238, 58,140),  "violetred2" },
       
   738   { QRGB(205, 50,120),  "violetred3" },
       
   739   { QRGB(139, 34, 82),  "violetred4" },
       
   740   { QRGB(245,222,179),  "wheat" },
       
   741   { QRGB(255,231,186),  "wheat1" },
       
   742   { QRGB(238,216,174),  "wheat2" },
       
   743   { QRGB(205,186,150),  "wheat3" },
       
   744   { QRGB(139,126,102),  "wheat4" },
       
   745   { QRGB(255,255,255),  "white" },
       
   746   { QRGB(245,245,245),  "whitesmoke" },
       
   747   { QRGB(255,255,  0),  "yellow" },
       
   748   { QRGB(255,255,  0),  "yellow1" },
       
   749   { QRGB(238,238,  0),  "yellow2" },
       
   750   { QRGB(205,205,  0),  "yellow3" },
       
   751   { QRGB(139,139,  0),  "yellow4" },
       
   752   { QRGB(154,205, 50),  "yellowgreen" } };
       
   753 
       
   754 #if defined(Q_C_CALLBACKS)
       
   755 extern "C" {
       
   756 #endif
       
   757 static int rgb_cmp(const void *d1, const void *d2)
       
   758 {
       
   759     return qstricmp(((XPMRGBData *)d1)->name, ((XPMRGBData *)d2)->name);
       
   760 }
       
   761 #if defined(Q_C_CALLBACKS)
       
   762 }
       
   763 #endif
       
   764 
       
   765 static bool qt_get_named_xpm_rgb(const char *name_no_space, QRgb *rgb)
       
   766 {
       
   767     XPMRGBData x;
       
   768     x.name = name_no_space;
       
   769     // Funtion bsearch() is supposed to be
       
   770     // void *bsearch(const void *key, const void *base, ...
       
   771     // So why (char*)? Are there broken bsearch() declarations out there?
       
   772     XPMRGBData *r = (XPMRGBData *)bsearch((char *)&x, (char *)xpmRgbTbl, xpmRgbTblSize,
       
   773                                           sizeof(XPMRGBData), rgb_cmp);
       
   774     if (r) {
       
   775         *rgb = r->value;
       
   776         return true;
       
   777     } else {
       
   778         return false;
       
   779     }
       
   780 }
       
   781 
       
   782 /*****************************************************************************
       
   783   Misc. utility functions
       
   784  *****************************************************************************/
       
   785 static QString fbname(const QString &fileName) // get file basename (sort of)
       
   786 {
       
   787     QString s = fileName;
       
   788     if (!s.isEmpty()) {
       
   789         int i;
       
   790         if ((i = s.lastIndexOf(QLatin1Char('/'))) >= 0)
       
   791             s = s.mid(i);
       
   792         if ((i = s.lastIndexOf(QLatin1Char('\\'))) >= 0)
       
   793             s = s.mid(i);
       
   794         QRegExp r(QLatin1String("[a-zA-Z][a-zA-Z0-9_]*"));
       
   795         int p = r.indexIn(s);
       
   796         if (p == -1)
       
   797             s.clear();
       
   798         else
       
   799             s = s.mid(p, r.matchedLength());
       
   800     }
       
   801     if (s.isEmpty())
       
   802         s = QString::fromLatin1("dummy");
       
   803     return s;
       
   804 }
       
   805 
       
   806 // Skip until ", read until the next ", return the rest in *buf
       
   807 // Returns false on error, true on success
       
   808 
       
   809 static bool read_xpm_string(QByteArray &buf, QIODevice *d, const char * const *source, int &index,
       
   810                             QByteArray &state)
       
   811 {
       
   812     if (source) {
       
   813         buf = source[index++];
       
   814         return true;
       
   815     }
       
   816 
       
   817     buf = "";
       
   818     bool gotQuote = false;
       
   819     int offset = 0;
       
   820     forever {
       
   821         if (offset == state.size() || state.isEmpty()) {
       
   822             char buf[2048];
       
   823             qint64 bytesRead = d->read(buf, sizeof(buf));
       
   824             if (bytesRead <= 0)
       
   825                 return false;
       
   826             state = QByteArray(buf, int(bytesRead));
       
   827             offset = 0;
       
   828         }
       
   829 
       
   830         if (!gotQuote) {
       
   831             if (state.at(offset++) == '"')
       
   832                 gotQuote = true;
       
   833         } else {
       
   834             char c = state.at(offset++);
       
   835             if (c == '"')
       
   836                 break;
       
   837             buf += c;
       
   838         }
       
   839     }
       
   840     state.remove(0, offset);
       
   841     return true;
       
   842 }
       
   843 
       
   844 // Tests if the given prefix can be the start of an XPM color specification
       
   845 
       
   846 static bool is_xpm_color_spec_prefix(const QByteArray& prefix)
       
   847 {
       
   848     return prefix == "c" ||
       
   849            prefix == "g" ||
       
   850            prefix == "g4" ||
       
   851            prefix == "m" ||
       
   852            prefix == "s";
       
   853 }
       
   854 
       
   855 // Reads XPM header.
       
   856 
       
   857 static bool read_xpm_header(
       
   858     QIODevice *device, const char * const * source, int& index, QByteArray &state,
       
   859     int *cpp, int *ncols, int *w, int *h)
       
   860 {
       
   861     QByteArray buf(200, 0);
       
   862 
       
   863     if (!read_xpm_string(buf, device, source, index, state))
       
   864         return false;
       
   865 
       
   866 #if defined(_MSC_VER) && _MSC_VER >= 1400 && !defined(Q_OS_WINCE)
       
   867         if (sscanf_s(buf, "%d %d %d %d", w, h, ncols, cpp) < 4)
       
   868 #else
       
   869     if (sscanf(buf, "%d %d %d %d", w, h, ncols, cpp) < 4)
       
   870 #endif
       
   871         return false;                                        // < 4 numbers parsed
       
   872 
       
   873     return true;
       
   874 }
       
   875 
       
   876 // Reads XPM body (color information & pixels).
       
   877 
       
   878 static bool read_xpm_body(
       
   879     QIODevice *device, const char * const * source, int& index, QByteArray& state,
       
   880     int cpp, int ncols, int w, int h, QImage& image)
       
   881 {
       
   882     QByteArray buf(200, 0);
       
   883     int i;
       
   884 
       
   885     if (cpp > 15)
       
   886         return false;
       
   887 
       
   888     // For > 256 colors, we delay creation of the image until
       
   889     // after we have read the color specifications, so that we can
       
   890     // create it in correct format (Format_RGB32 vs Format_ARGB32,
       
   891     // depending on absence or presence of "c none", respectively)
       
   892     if (ncols <= 256) {
       
   893         if (image.size() != QSize(w, h) || image.format() != QImage::Format_Indexed8) {
       
   894             image = QImage(w, h, QImage::Format_Indexed8);
       
   895             if (image.isNull())
       
   896                 return false;
       
   897         }
       
   898         image.setNumColors(ncols);
       
   899     }
       
   900 
       
   901     QMap<quint64, int> colorMap;
       
   902     int currentColor;
       
   903     bool hasTransparency = false;
       
   904 
       
   905     for(currentColor=0; currentColor < ncols; ++currentColor) {
       
   906         if (!read_xpm_string(buf, device, source, index, state)) {
       
   907             qWarning("QImage: XPM color specification missing");
       
   908             return false;
       
   909         }
       
   910         QByteArray index;
       
   911         index = buf.left(cpp);
       
   912         buf = buf.mid(cpp).simplified().trimmed().toLower();
       
   913         QList<QByteArray> tokens = buf.split(' ');
       
   914         i = tokens.indexOf("c");
       
   915         if (i < 0)
       
   916             i = tokens.indexOf("g");
       
   917         if (i < 0)
       
   918             i = tokens.indexOf("g4");
       
   919         if (i < 0)
       
   920             i = tokens.indexOf("m");
       
   921         if (i < 0) {
       
   922             qWarning("QImage: XPM color specification is missing: %s", buf.constData());
       
   923             return false;        // no c/g/g4/m specification at all
       
   924         }
       
   925         QByteArray color;
       
   926         while ((++i < tokens.size()) && !is_xpm_color_spec_prefix(tokens.at(i))) {
       
   927             color.append(tokens.at(i));
       
   928         }
       
   929         if (color.isEmpty()) {
       
   930             qWarning("QImage: XPM color value is missing from specification: %s", buf.constData());
       
   931             return false;        // no color value
       
   932         }
       
   933         buf = color;
       
   934         if (buf == "none") {
       
   935             hasTransparency = true;
       
   936             int transparentColor = currentColor;
       
   937             if (ncols <= 256) {
       
   938                 image.setColor(transparentColor, 0);
       
   939                 colorMap.insert(xpmHash(QLatin1String(index.constData())), transparentColor);
       
   940             } else {
       
   941                 colorMap.insert(xpmHash(QLatin1String(index.constData())), 0);
       
   942             }
       
   943         } else {
       
   944             QRgb c_rgb;
       
   945             if (((buf.length()-1) % 3) && (buf[0] == '#')) {
       
   946                 buf.truncate(((buf.length()-1) / 4 * 3) + 1); // remove alpha channel left by imagemagick
       
   947             }
       
   948             if (buf[0] == '#') {
       
   949                 qt_get_hex_rgb(buf, &c_rgb);
       
   950             } else {
       
   951                 qt_get_named_xpm_rgb(buf, &c_rgb);
       
   952             }
       
   953             if (ncols <= 256) {
       
   954                 image.setColor(currentColor, 0xff000000 | c_rgb);
       
   955                 colorMap.insert(xpmHash(QLatin1String(index.constData())), currentColor);
       
   956             } else {
       
   957                 colorMap.insert(xpmHash(QLatin1String(index.constData())), 0xff000000 | c_rgb);
       
   958             }
       
   959         }
       
   960     }
       
   961 
       
   962     if (ncols > 256) {
       
   963         // Now we can create 32-bit image of appropriate format
       
   964         QImage::Format format = hasTransparency ?
       
   965                                 QImage::Format_ARGB32 : QImage::Format_RGB32;
       
   966         if (image.size() != QSize(w, h) || image.format() != format) {
       
   967             image = QImage(w, h, format);
       
   968             if (image.isNull())
       
   969                 return false;
       
   970         }
       
   971     }
       
   972 
       
   973     // Read pixels
       
   974     for(int y=0; y<h; y++) {
       
   975         if (!read_xpm_string(buf, device, source, index, state)) {
       
   976             qWarning("QImage: XPM pixels missing on image line %d", y);
       
   977             return false;
       
   978         }
       
   979         if (image.depth() == 8) {
       
   980             uchar *p = image.scanLine(y);
       
   981             uchar *d = (uchar *)buf.data();
       
   982             uchar *end = d + buf.length();
       
   983             int x;
       
   984             if (cpp == 1) {
       
   985                 char b[2];
       
   986                 b[1] = '\0';
       
   987                 for (x=0; x<w && d<end; x++) {
       
   988                     b[0] = *d++;
       
   989                     *p++ = (uchar)colorMap[xpmHash(b)];
       
   990                 }
       
   991             } else {
       
   992                 char b[16];
       
   993                 b[cpp] = '\0';
       
   994                 for (x=0; x<w && d<end; x++) {
       
   995                     memcpy(b, (char *)d, cpp);
       
   996                     *p++ = (uchar)colorMap[xpmHash(b)];
       
   997                     d += cpp;
       
   998                 }
       
   999             }
       
  1000             // avoid uninitialized memory for malformed xpms
       
  1001             if (x < w) {
       
  1002                 qWarning("QImage: XPM pixels missing on image line %d (possibly a C++ trigraph).", y);
       
  1003                 memset(p, 0, w - x);
       
  1004             }
       
  1005         } else {
       
  1006             QRgb *p = (QRgb*)image.scanLine(y);
       
  1007             uchar *d = (uchar *)buf.data();
       
  1008             uchar *end = d + buf.length();
       
  1009             int x;
       
  1010             char b[16];
       
  1011             b[cpp] = '\0';
       
  1012             for (x=0; x<w && d<end; x++) {
       
  1013                 memcpy(b, (char *)d, cpp);
       
  1014                 *p++ = (QRgb)colorMap[xpmHash(b)];
       
  1015                 d += cpp;
       
  1016             }
       
  1017             // avoid uninitialized memory for malformed xpms
       
  1018             if (x < w) {
       
  1019                 qWarning("QImage: XPM pixels missing on image line %d (possibly a C++ trigraph).", y);
       
  1020                 memset(p, 0, (w - x)*4);
       
  1021             }
       
  1022         }
       
  1023     }
       
  1024 
       
  1025     if (device) {
       
  1026         // Rewind unused characters, and skip to the end of the XPM struct.
       
  1027         for (int i = state.size() - 1; i >= 0; --i)
       
  1028             device->ungetChar(state[i]);
       
  1029         char c;
       
  1030         while (device->getChar(&c) && c != ';') {}
       
  1031         while (device->getChar(&c) && c != '\n') {}
       
  1032     }
       
  1033     return true;
       
  1034 }
       
  1035 
       
  1036 //
       
  1037 // INTERNAL
       
  1038 //
       
  1039 // Reads an .xpm from either the QImageIO or from the QString *.
       
  1040 // One of the two HAS to be 0, the other one is used.
       
  1041 //
       
  1042 
       
  1043 bool qt_read_xpm_image_or_array(QIODevice *device, const char * const * source, QImage &image)
       
  1044 {
       
  1045     if (!source)
       
  1046         return true;
       
  1047 
       
  1048     QByteArray buf(200, 0);
       
  1049     QByteArray state;
       
  1050 
       
  1051     int cpp, ncols, w, h, index = 0;
       
  1052 
       
  1053     if (device) {
       
  1054         // "/* XPM */"
       
  1055         int readBytes;
       
  1056         if ((readBytes = device->readLine(buf.data(), buf.size())) < 0)
       
  1057             return false;
       
  1058 
       
  1059         if (buf.indexOf("/* XPM") != 0) {
       
  1060             while (readBytes > 0) {
       
  1061                 device->ungetChar(buf.at(readBytes - 1));
       
  1062                 --readBytes;
       
  1063             }
       
  1064             return false;
       
  1065         }// bad magic
       
  1066     }
       
  1067 
       
  1068     if (!read_xpm_header(device, source, index, state, &cpp, &ncols, &w, &h))
       
  1069         return false;
       
  1070 
       
  1071     return read_xpm_body(device, source, index, state, cpp, ncols, w, h, image);
       
  1072 }
       
  1073 
       
  1074 static const char* xpm_color_name(int cpp, int index)
       
  1075 {
       
  1076     static char returnable[5];
       
  1077     static const char code[] = ".#abcdefghijklmnopqrstuvwxyzABCD"
       
  1078                                "EFGHIJKLMNOPQRSTUVWXYZ0123456789";
       
  1079     // cpp is limited to 4 and index is limited to 64^cpp
       
  1080     if (cpp > 1) {
       
  1081         if (cpp > 2) {
       
  1082             if (cpp > 3) {
       
  1083                 returnable[3] = code[index % 64];
       
  1084                 index /= 64;
       
  1085             } else
       
  1086                 returnable[3] = '\0';
       
  1087             returnable[2] = code[index % 64];
       
  1088             index /= 64;
       
  1089         } else
       
  1090             returnable[2] = '\0';
       
  1091         // the following 4 lines are a joke!
       
  1092         if (index == 0)
       
  1093             index = 64*44+21;
       
  1094         else if (index == 64*44+21)
       
  1095             index = 0;
       
  1096         returnable[1] = code[index % 64];
       
  1097         index /= 64;
       
  1098     } else
       
  1099         returnable[1] = '\0';
       
  1100     returnable[0] = code[index];
       
  1101 
       
  1102     return returnable;
       
  1103 }
       
  1104 
       
  1105 
       
  1106 // write XPM image data
       
  1107 static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const QString &fileName)
       
  1108 {
       
  1109     if (!device->isWritable())
       
  1110         return false;
       
  1111 
       
  1112     QImage image;
       
  1113     if (sourceImage.depth() != 32)
       
  1114         image = sourceImage.convertToFormat(QImage::Format_RGB32);
       
  1115     else
       
  1116         image = sourceImage;
       
  1117 
       
  1118     QMap<QRgb, int> colorMap;
       
  1119 
       
  1120     int w = image.width(), h = image.height(), ncolors = 0;
       
  1121     int x, y;
       
  1122 
       
  1123     // build color table
       
  1124     for(y=0; y<h; y++) {
       
  1125         QRgb * yp = (QRgb *)image.scanLine(y);
       
  1126         for(x=0; x<w; x++) {
       
  1127             QRgb color = *(yp + x);
       
  1128             if (!colorMap.contains(color))
       
  1129                 colorMap.insert(color, ncolors++);
       
  1130         }
       
  1131     }
       
  1132 
       
  1133     // number of 64-bit characters per pixel needed to encode all colors
       
  1134     int cpp = 1;
       
  1135     for (int k = 64; ncolors > k; k *= 64) {
       
  1136         ++cpp;
       
  1137         // limit to 4 characters per pixel
       
  1138         // 64^4 colors is enough for a 4096x4096 image
       
  1139          if (cpp > 4)
       
  1140             break;
       
  1141     }
       
  1142 
       
  1143     QString line;
       
  1144 
       
  1145     // write header
       
  1146     QTextStream s(device);
       
  1147     s << "/* XPM */" << endl
       
  1148       << "static char *" << fbname(fileName) << "[]={" << endl
       
  1149       << '\"' << w << ' ' << h << ' ' << ncolors << ' ' << cpp << '\"';
       
  1150 
       
  1151     // write palette
       
  1152     QMap<QRgb, int>::Iterator c = colorMap.begin();
       
  1153     while (c != colorMap.end()) {
       
  1154         QRgb color = c.key();
       
  1155         if (image.format() != QImage::Format_RGB32 && !qAlpha(color))
       
  1156             line.sprintf("\"%s c None\"",
       
  1157                           xpm_color_name(cpp, *c));
       
  1158         else
       
  1159             line.sprintf("\"%s c #%02x%02x%02x\"",
       
  1160                           xpm_color_name(cpp, *c),
       
  1161                           qRed(color),
       
  1162                           qGreen(color),
       
  1163                           qBlue(color));
       
  1164         ++c;
       
  1165         s << ',' << endl << line;
       
  1166     }
       
  1167 
       
  1168     // write pixels, limit to 4 characters per pixel
       
  1169     line.truncate(cpp*w);
       
  1170     for(y=0; y<h; y++) {
       
  1171         QRgb * yp = (QRgb *) image.scanLine(y);
       
  1172         int cc = 0;
       
  1173         for(x=0; x<w; x++) {
       
  1174             int color = (int)(*(yp + x));
       
  1175             QByteArray chars(xpm_color_name(cpp, colorMap[color]));
       
  1176             line[cc++] = QLatin1Char(chars[0]);
       
  1177             if (cpp > 1) {
       
  1178                 line[cc++] = QLatin1Char(chars[1]);
       
  1179                 if (cpp > 2) {
       
  1180                     line[cc++] = QLatin1Char(chars[2]);
       
  1181                     if (cpp > 3) {
       
  1182                         line[cc++] = QLatin1Char(chars[3]);
       
  1183                     }
       
  1184                 }
       
  1185             }
       
  1186         }
       
  1187         s << ',' << endl << '\"' << line << '\"';
       
  1188     }
       
  1189     s << "};" << endl;
       
  1190     return (s.status() == QTextStream::Ok);
       
  1191 }
       
  1192 
       
  1193 QXpmHandler::QXpmHandler()
       
  1194     : state(Ready), index(0)
       
  1195 {
       
  1196 }
       
  1197 
       
  1198 bool QXpmHandler::readHeader()
       
  1199 {
       
  1200     state = Error;
       
  1201     if (!read_xpm_header(device(), 0, index, buffer, &cpp, &ncols, &width, &height))
       
  1202         return false;
       
  1203     state = ReadHeader;
       
  1204     return true;
       
  1205 }
       
  1206 
       
  1207 bool QXpmHandler::readImage(QImage *image)
       
  1208 {
       
  1209     if (state == Error)
       
  1210         return false;
       
  1211 
       
  1212     if (state == Ready && !readHeader()) {
       
  1213         state = Error;
       
  1214         return false;
       
  1215     }
       
  1216 
       
  1217     if (!read_xpm_body(device(), 0, index, buffer, cpp, ncols, width, height, *image)) {
       
  1218         state = Error;
       
  1219         return false;
       
  1220     }
       
  1221 
       
  1222     state = Ready;
       
  1223     return true;
       
  1224 }
       
  1225 
       
  1226 bool QXpmHandler::canRead() const
       
  1227 {
       
  1228     if (state == Ready && canRead(device())) {
       
  1229         setFormat("xpm");
       
  1230         return true;
       
  1231     }
       
  1232     return state != Error;
       
  1233 }
       
  1234 
       
  1235 bool QXpmHandler::canRead(QIODevice *device)
       
  1236 {
       
  1237     if (!device) {
       
  1238         qWarning("QXpmHandler::canRead() called with no device");
       
  1239         return false;
       
  1240     }
       
  1241 
       
  1242     char head[6];
       
  1243     if (device->peek(head, sizeof(head)) != sizeof(head))
       
  1244         return false;
       
  1245 
       
  1246     return qstrncmp(head, "/* XPM", 6) == 0;
       
  1247 }
       
  1248 
       
  1249 bool QXpmHandler::read(QImage *image)
       
  1250 {
       
  1251     if (!canRead())
       
  1252         return false;
       
  1253     return readImage(image);
       
  1254 }
       
  1255 
       
  1256 bool QXpmHandler::write(const QImage &image)
       
  1257 {
       
  1258     return write_xpm_image(image, device(), fileName);
       
  1259 }
       
  1260 
       
  1261 bool QXpmHandler::supportsOption(ImageOption option) const
       
  1262 {
       
  1263     return option == Name
       
  1264         || option == Size
       
  1265         || option == ImageFormat;
       
  1266 }
       
  1267 
       
  1268 QVariant QXpmHandler::option(ImageOption option) const
       
  1269 {
       
  1270     if (option == Name) {
       
  1271         return fileName;
       
  1272     } else if (option == Size) {
       
  1273         if (state == Error)
       
  1274             return QVariant();
       
  1275         if (state == Ready && !const_cast<QXpmHandler*>(this)->readHeader())
       
  1276             return QVariant();
       
  1277         return QSize(width, height);
       
  1278     } else if (option == ImageFormat) {
       
  1279         if (state == Error)
       
  1280             return QVariant();
       
  1281         if (state == Ready && !const_cast<QXpmHandler*>(this)->readHeader())
       
  1282             return QVariant();
       
  1283         // If we have more than 256 colors in the table, we need to
       
  1284         // figure out, if it contains transparency. That means reading
       
  1285         // the whole color table, which is too much work work pre-checking
       
  1286         // the image format
       
  1287         if (ncols <= 256)
       
  1288             return QImage::Format_Indexed8;
       
  1289         else
       
  1290             return QImage::Format_Invalid;
       
  1291     }
       
  1292 
       
  1293     return QVariant();
       
  1294 }
       
  1295 
       
  1296 void QXpmHandler::setOption(ImageOption option, const QVariant &value)
       
  1297 {
       
  1298     if (option == Name)
       
  1299         fileName = value.toString();
       
  1300 }
       
  1301 
       
  1302 QByteArray QXpmHandler::name() const
       
  1303 {
       
  1304     return "xpm";
       
  1305 }
       
  1306 
       
  1307 QT_END_NAMESPACE
       
  1308 
       
  1309 #endif // QT_NO_IMAGEFORMAT_XPM