ioacolorpopup.c

Go to the documentation of this file.
00001 
00002 /*  $Id: ioacolorpopup.c 1197 2006-04-05 22:01:22Z karstenw $    */
00003 
00004 /******************************************************************************
00005 
00006     UserLand Frontier(tm) -- High performance Web content management,
00007     object database, system-level and Internet scripting environment,
00008     including source code editing and debugging.
00009 
00010     Copyright (C) 1992-2004 UserLand Software, Inc.
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 
00026 ******************************************************************************/
00027 
00028 /*original code by Dave Shaver, Quark, 303-849-3311, adapted by DW 2/9/93. Thanks Dave!*/
00029 
00030 #include "frontier.h"
00031 #include "standard.h"
00032 
00033 #include <iac.h>
00034 #include <ioa.h>
00035 #include "ioacolorpopup.h"
00036 
00037 #define colorpopuptype -3
00038 
00039 #define mPopupMsg 3 /*this MDEF message isn't in the headers*/
00040 
00041 #define outsetsize 1
00042 
00043 #define itemsize 10
00044 
00045 #define boxinset 5 /*the number of pixels to skip between box and text*/
00046 
00047 #define textvertinset 2
00048 
00049 #define gestalttrap 0xA1AD
00050 
00051 #define unimplementedtrap 0xA09F
00052 
00053 
00054 static boolean gestaltavailable (void) {
00055     //Code change by Timothy Paustian Sunday, June 25, 2000 10:33:59 PM
00056     //Gestalt is available in OS 9 and X
00057     #if TARGET_API_MAC_CARBON == 1
00058     return true;
00059     #else
00060         
00061     UniversalProcPtr gestaltaddr;
00062     UniversalProcPtr unimplementedaddr;
00063 
00064     gestaltaddr = NGetTrapAddress (gestalttrap, ToolTrap);
00065     
00066     unimplementedaddr = NGetTrapAddress (unimplementedtrap, ToolTrap);
00067     
00068     return (unimplementedaddr != gestaltaddr);  
00069     #endif
00070         
00071     } /*gestaltavailable*/
00072     
00073     
00074 static boolean getgestaltattr (OSType selector, long *response) {
00075     
00076     OSErr errcode;
00077     
00078     if (!gestaltavailable ())
00079         return (false);
00080         
00081     errcode = Gestalt (selector, response);
00082     
00083     return (errcode == noErr);
00084     } /*getgestaltattr*/
00085     
00086     
00087 static boolean systemhascolor (void) {
00088 
00089     long templong;
00090     
00091     if (!getgestaltattr (gestaltQuickdrawVersion, &templong))
00092         return (false);
00093     
00094     return (templong >= gestalt8BitQD);
00095     } /*systemhascolor*/
00096 
00097 
00098 #if !TARGET_API_MAC_CARBON
00099 
00100 static void getitemrect (short item, Rect *ritem) {
00101 
00102     short x, y;
00103     Rect r;
00104     
00105     item--;
00106     
00107     x = item % 32;
00108     
00109     y = item / 32;
00110     
00111     r.top = 1 + y * itemsize;
00112     
00113     r.left = 1 + x * itemsize;
00114     
00115     r.bottom = r.top + itemsize;
00116     
00117     r.right = r.left + itemsize;
00118     
00119     *ritem = r;
00120     } /*getitemrect*/
00121     
00122     
00123 static void frameitem (short item, Rect menurect) {
00124 
00125     Rect r;
00126     PenState ps;
00127     
00128     if (item <= 0)
00129         return;
00130         
00131     IOApushforecolor (&blackcolor);
00132     
00133     GetPenState (&ps);
00134     
00135     PenMode (patCopy);// (patXor);
00136     
00137     getitemrect (item, &r);
00138     
00139     OffsetRect (&r, menurect.left, menurect.top);
00140     
00141     FrameRect (&r);
00142     
00143     SetPenState (&ps);
00144     
00145     IOApopforecolor ();
00146     } /*frameitem*/
00147     
00148 
00149 static pascal void colormenuhandler (short msg, MenuHandle hmenu, Rect *menurect, Point pt, short *item) {
00150 
00151     #ifndef IOAinsideApp
00152 
00153         SetUpA4 ();
00154     
00155     #endif
00156 
00157     switch (msg) {
00158     
00159         case mDrawMsg: {
00160             short i, j;
00161             Rect r; 
00162             CSpecArray *ctable;
00163             
00164             ctable = (CSpecArray *) &(**GetCTable (8)).ctTable;
00165             
00166             IOApushforecolor (&lightbluecolor);
00167             
00168             PaintRect ((const Rect *) &menurect);
00169             
00170             for (i = 0; i < 8; i++) {
00171             
00172                 for (j = 0; j < 32; j++) {
00173                 
00174                     getitemrect (i * 32 + j + 1, &r);
00175                     
00176                     OffsetRect (&r, (*menurect).left, (*menurect).top);
00177                     
00178                     RGBForeColor (&blackcolor);
00179                     
00180                     InsetRect (&r, 1, 1);
00181                     
00182                     PaintRect (&r);
00183                     
00184                     InsetRect (&r, 1, 1);
00185                     
00186                     RGBForeColor (&(*ctable) [i * 32 + j].rgb);
00187                     
00188                     PaintRect (&r);
00189                     } /*for*/
00190                 } /*for*/
00191             
00192             IOApopforecolor ();
00193             
00194             break;
00195             }
00196             
00197         #if TARGET_API_MAC_CARBON
00198         case kMenuHiliteItemMsg: {
00199         #else
00200         case mChooseMsg: {
00201         #endif
00202             short nextitem;
00203             Rect rinset;
00204             
00205             rinset = *menurect;
00206             
00207             InsetRect (&rinset, outsetsize, outsetsize);
00208             
00209             if (!PtInRect (pt, &rinset)) 
00210                 nextitem = 0;
00211             else {
00212                 nextitem = 
00213                     32L * ((pt.v - (*menurect).top - outsetsize) / itemsize) +
00214                     (pt.h - (*menurect).left - outsetsize) / itemsize + 1;
00215                 
00216                 if (nextitem < 0) 
00217                     nextitem = 0;
00218                 }
00219                 
00220             if (*item == nextitem) /*already highlighted*/
00221                 break;
00222                 
00223             frameitem (*item, *menurect); /*unhighlight the original item*/
00224         
00225             frameitem (nextitem, *menurect); /*highlight the newly selected item*/
00226                 
00227             *item = nextitem;
00228             
00229             break;
00230             }
00231             
00232         case mSizeMsg:
00233             //Code change by Timothy Paustian Friday, May 5, 2000 11:03:07 PM
00234             //Changed to Opaque call for Carbon
00235             //untested but should be fine.
00236             #if ACCESSOR_CALLS_ARE_FUNCTIONS == 1
00237             SetMenuHeight(hmenu, 8L * itemsize + 2);
00238             SetMenuWidth(hmenu, 32L * itemsize + 2);
00239             #else
00240             (**hmenu).menuHeight = 8L * itemsize + 2;
00241             (**hmenu).menuWidth = 32L * itemsize + 2;
00242             #endif
00243             
00244             break;
00245             
00246         case mPopupMsg:
00247             //Code change by Timothy Paustian Friday, May 5, 2000 11:05:34 PM
00248             //Changed to Opaque call for Carbon
00249             //untested, but again simple.
00250             {
00251             int menuHeight, menuWidth;
00252             #if ACCESSOR_CALLS_ARE_FUNCTIONS == 1
00253             menuHeight = GetMenuHeight(hmenu);
00254             menuWidth = GetMenuWidth(hmenu);
00255             #else
00256             menuHeight = (**hmenu).menuHeight;
00257             menuWidth = (**hmenu).menuWidth;
00258             #endif
00259             (*menurect).top = pt.h;
00260             
00261             (*menurect).left = pt.v;
00262             
00263             (*menurect).bottom = (*menurect).top + menuHeight;
00264             
00265             (*menurect).right = (*menurect).left + menuWidth;
00266             }
00267             break;
00268         } /*switch*/
00269 
00270     #ifndef IOAinsideApp
00271 
00272         RestoreA4 ();
00273     
00274     #endif
00275     } /*colormenuhandler*/
00276 
00277     
00278 static void DebugNum (long num) {
00279     
00280     bigstring bs;
00281     
00282     NumToString (num, bs);
00283     
00284     DebugStr (bs);
00285     } /*DebugNum*/
00286 
00287 #if !GENERATINGCFM
00288 
00289 typedef struct Jump68kDescriptor {
00290     
00291     short jmp;
00292     
00293     ProcPtr adr;
00294     } Jump68kDescriptor;
00295 
00296 #define BUILD_JUMP68K_DESCRIPTOR(procedure)  \
00297     {                               \
00298     0x4EF9,                         \
00299     (ProcPtr)(procedure),           \
00300     }
00301 
00302 #endif
00303 #endif
00304 
00305 static boolean colormenuclick (Point pt, RGBColor *rgb) {
00306     
00307     /*
00308     4.1b3 dmb: updated for ppc compatibility
00309     */
00310     
00311     long result;
00312     MenuHandle colormenu;
00313     #if TARGET_API_MAC_CARBON == 1
00314     #else
00315         
00316     #if GENERATINGCFM
00317         RoutineDescriptor mdefstub = BUILD_ROUTINE_DESCRIPTOR (uppMenuDefProcInfo, colormenuhandler);
00318     #else
00319         Jump68kDescriptor mdefstub = BUILD_JUMP68K_DESCRIPTOR (colormenuhandler);
00320     #endif
00321     Handle hmdefstub;
00322     #endif
00323     short lo, hi;
00324         
00325     #ifndef IOAinsideApp
00326 
00327         RememberA4 ();
00328     
00329     #endif
00330 
00331     if (!systemhascolor ()) 
00332         return (false);
00333         
00334     IOAopenresfile ();
00335     
00336     colormenu = GetMenu (256);
00337 
00338     
00339     #if !TARGET_API_MAC_CARBON
00340     hmdefstub = NewHandle (sizeof (mdefstub));
00341     
00342     #if GENERATINGCFM
00343         **(RoutineDescriptor **) hmdefstub = mdefstub;
00344     #else
00345         **(Jump68kDescriptor **) hmdefstub = mdefstub;
00346     #endif
00347     #endif
00348 //Code change by Timothy Paustian Saturday, May 6, 2000 10:27:09 PM
00349     //Changed to Opaque call for Carbon
00350     //This may need to be more complex, mention this to Andre.
00351     //I really need to test this.
00352     //It isn't used as far as I can tell. Ask Andre.
00353     #if ACCESSOR_CALLS_ARE_FUNCTIONS == 1
00354     //where is this library routine. I need to find out where
00355     //this is defined.
00356     //SetMenuDefinition(colormenu, hmdefstub);
00357     //(**colormenu).menuProc = hmdefstub;
00358     //lets not install one.
00359     #else
00360     (**colormenu).menuProc = hmdefstub;
00361     #endif  
00362     CalcMenuSize (colormenu);
00363         
00364     InsertMenu (colormenu, hierMenu);
00365 
00366     LocalToGlobal (&pt);
00367     
00368     result = PopUpMenuSelect (colormenu, pt.v, pt.h, 1);
00369     
00370     #if !TARGET_API_MAC_CARBON
00371     DisposeHandle (hmdefstub);
00372     #endif
00373     //Code change by Timothy Paustian Saturday, May 6, 2000 10:35:10 PM
00374     //Changed to Opaque call for Carbon
00375     //I changed this to dispose menu, it does the same thing
00376     DisposeMenu (colormenu);
00377     //old code
00378     //DeleteMenu ((**colormenu).menuID);
00379     
00380     IOAcloseresfile ();
00381     
00382     lo = LoWord (result);
00383     
00384     hi = HiWord (result);
00385     
00386     if (hi > 0) { /*something was selected*/
00387     
00388         CSpecArray *ctable;
00389         
00390         ctable = (CSpecArray *) &(**GetCTable (8)).ctTable;
00391 
00392         *rgb = (*ctable) [lo - 1].rgb;
00393         
00394         return (true);
00395         }
00396     
00397     return (false);
00398     } /*colormenuclick*/
00399     
00400 
00401 static void getcolorrect (hdlobject h, Rect r, Rect *rbox) {
00402     
00403     hdlcard hc = (**h).owningcard;
00404     short objectfontsize = (**h).objectfontsize;
00405     FontInfo fi = (**hc).fontinfo;
00406     short lineheight;
00407     short extrapixels;
00408     
00409     lineheight = fi.ascent + fi.descent + fi.leading;
00410     
00411     extrapixels = (lineheight - objectfontsize) / 2;
00412     
00413     r.top += textvertinset;
00414     
00415     if (extrapixels > 0)
00416         r.top += (lineheight - objectfontsize) - extrapixels;
00417     
00418     r.bottom = r.top + objectfontsize;
00419     
00420     r.left += 3;
00421     
00422     r.right = r.left + objectfontsize;
00423     
00424     *rbox = r;
00425     } /*getcolorrect*/
00426     
00427 
00428 static boolean getcoloreditrect (hdlobject h, Rect *r) {
00429 
00430     *r = (**h).objectrect;
00431         
00432     (*r).left += 3 + (**h).objectfontsize + boxinset;
00433     
00434     return (true); /*it can be edited*/
00435     } /*getcoloreditrect*/
00436     
00437 
00438 static boolean clickcolorpopup (hdlobject listhead, hdlobject h, Point pt, boolean flshiftkey, boolean fl2click) {
00439 #pragma unused(listhead, flshiftkey, fl2click)
00440 
00441     hdlcolordata hdata = (hdlcolordata) (**h).objectdata;
00442     RGBColor rgb;
00443     
00444     if (!systemhascolor ()) 
00445         return (false);
00446         
00447     if (!colormenuclick (pt, &rgb))
00448         return (false);
00449         
00450     (**hdata).rgb = rgb;
00451         
00452     (**(**h).owningcard).runtimevaluechanged = true; /*DW 10/13/95*/
00453     
00454     IOAinvalobject (h);
00455     
00456     IOArunbuttonscript (h); /*1.0b15 -- run the action script*/
00457     
00458     return (true); /*do a minor recalc*/
00459     } /*clickcolorpopup*/
00460     
00461     
00462 static boolean cleancolorpopup (hdlobject h, short height, short width, Rect *r) {
00463 
00464     hdlcard hc = (**h).owningcard;
00465     short gridunits = (**hc).gridunits;
00466     
00467     width = IOAmakemultiple (width + 3 + (**h).objectfontsize + boxinset, gridunits);
00468     
00469     (*r).right = (*r).left + width;
00470     
00471     (*r).bottom = (*r).top + height;
00472     
00473     return (true);
00474     } /*cleancolorpopup*/
00475     
00476 
00477 static boolean canreplicatecolorpopup (hdlobject h) {
00478 #pragma unused(h)
00479     return (true); 
00480     } /*canreplicatecolorpopup*/
00481     
00482 
00483 #if 0
00484 
00485 static boolean getcheckboxeditrect (hdlobject h, Rect *r) {
00486 
00487     *r = (**h).objectrect;
00488         
00489     (*r).left += 3 + (**h).objectfontsize + boxinset;
00490     
00491     return (true); /*it can be edited*/
00492     } /*getcheckboxeditrect*/
00493 
00494 #endif
00495     
00496 
00497 static void pushlong (long num, bigstring bs) {
00498     
00499     bigstring bsnum;
00500     
00501     NumToString (num, bsnum);
00502     
00503     IOApushstring (bsnum, bs);
00504     } /*pushlong*/
00505     
00506     
00507 static boolean getcolorpopupvalue (hdlobject h, Handle *hvalue) {
00508     
00509     hdlcolordata hdata = (hdlcolordata) (**h).objectdata;
00510     RGBColor rgb = (**hdata).rgb;
00511     bigstring bs;
00512     
00513     IOAcopystring ("\p\"", bs);
00514     
00515     pushlong (rgb.red, bs);
00516     
00517     IOApushstring ("\p,", bs);
00518     
00519     pushlong (rgb.green, bs);
00520     
00521     IOApushstring ("\p,", bs);
00522 
00523     pushlong (rgb.blue, bs);
00524     
00525     IOApushstring ("\p\"", bs);
00526     
00527     return (IOAnewtexthandle (bs, hvalue));
00528     } /*getcolorpopupvalue*/
00529     
00530     
00531 static void poplong (bigstring bs, unsigned short *x) {
00532     
00533     bigstring bsnum;
00534     long longval;
00535     
00536     bsnum [0] = 0;
00537     
00538     while (true) {
00539         
00540         short len;
00541         char ch;
00542         
00543         len = bs [0];
00544         
00545         if (len == 0)
00546             break;
00547             
00548         ch = bs [1];
00549         
00550         BlockMove (&bs [2], &bs [1], --len);
00551         
00552         bs [0] = len;
00553         
00554         if ((ch < '0') || (ch > '9')) 
00555             break;
00556             
00557         len = bsnum [0] + 1;
00558         
00559         bsnum [0] = len;
00560         
00561         bsnum [len] = ch;
00562         } /*while*/
00563     
00564     StringToNum (bsnum, &longval);
00565     
00566     *x = longval;
00567     } /*poplong*/
00568     
00569 
00570 static boolean setcolorpopupvalue (hdlobject h, Handle hvalue) {
00571 
00572     hdlcolordata hdata = (hdlcolordata) (**h).objectdata;
00573     bigstring bs;
00574     RGBColor rgb;
00575     
00576     if (hvalue == nil)
00577         return (true);
00578         
00579     IOAtexthandletostring (hvalue, bs);
00580     
00581     DisposeHandle (hvalue);
00582     
00583     poplong (bs, &rgb.red);
00584     
00585     poplong (bs, &rgb.green);
00586     
00587     poplong (bs, &rgb.blue);
00588     
00589     (**hdata).rgb = rgb;
00590     
00591     return (true);
00592     } /*setcolorpopupvalue*/
00593 
00594 
00595 static boolean debugcolorpopup (hdlobject h, bigstring errorstring) {
00596 #pragma unused(h)
00597     setstringlength (errorstring, 0);
00598     
00599     return (true);
00600     } /*debugcolorpopup*/
00601     
00602     
00603 static boolean drawcolorobject (hdlobject h) {
00604     
00605     hdlcard hc = (**h).owningcard;
00606     hdlcolordata hdata = (hdlcolordata) (**h).objectdata;
00607     RGBColor rgb = (**hdata).rgb;
00608     Rect rbox;
00609     Rect r;
00610     Handle htext;
00611     
00612     htext = (**h).objectvalue; 
00613     
00614     r = (**h).objectrect;
00615     
00616     if (!(**h).objecttransparent)
00617         EraseRect (&r);
00618         
00619     getcolorrect (h, r, &rbox);
00620     
00621     if (!(**h).objectenabled)
00622         rgb.red = rgb.green = rgb.blue = 61166; /*light gray*/
00623         
00624     IOApushbackcolor (&rgb);
00625 
00626     EraseRect (&rbox);
00627     
00628     IOApopbackcolor ();
00629         
00630     FrameRect (&rbox);
00631     
00632     if ((**hc).tracking && (**hc).trackerpressed) {
00633         
00634         Rect rinset = rbox;
00635         
00636         InsetRect (&rinset, 1, 1);
00637         
00638         FrameRect (&rinset);
00639         }
00640     
00641     if (!(**hc).flskiptext) {
00642         
00643         Rect rtext;
00644         
00645         getcoloreditrect (h, &rtext);
00646         
00647         IOAeditdrawtexthandle (htext, rtext, (**h).objectjustification);
00648         }
00649     
00650     return (true);
00651     } /*drawcolorobject*/
00652     
00653     
00654 static boolean newcolordata (hdlcolordata *hdata) {
00655 
00656     hdlcolordata h;
00657     
00658     h = (hdlcolordata) NewHandleClear (longsizeof (tycolordata));
00659     
00660     if (h == nil)
00661         return (false);
00662     
00663     (**h).versionnumber = 1;
00664     
00665     (**h).rgb = lightbluecolor;
00666     
00667     *hdata = h;
00668     
00669     return (true);
00670     } /*newcolordata*/
00671     
00672     
00673 static boolean initcolorpopup (tyobject *obj) {
00674     
00675     newcolordata ((hdlcolordata *) &(*obj).objectdata);
00676     
00677     return (true); /*nothing special, we do want to edit it*/
00678     } /*initcolorpopup*/
00679     
00680     
00681 static boolean unpackcolordata (hdlobject h) {
00682     
00683     hdlcolordata hdata = (hdlcolordata) (**h).objectdata;
00684     
00685     if (hdata == nil) { /*pre 1.0b15 object, no data handle*/
00686         
00687         if (!newcolordata (&hdata))
00688             return (false);
00689             
00690         (**h).objectdata = (Handle) hdata;
00691         
00692         return (true);
00693         }
00694         
00695     return (true);
00696     } /*unpackcolordata*/
00697 
00698 
00699 static boolean getcolorattributes (hdlobject h, AppleEvent *event) {
00700     
00701     hdlcolordata hdata = (hdlcolordata) (**h).objectdata;
00702     RGBColor rgb = (**hdata).rgb;
00703     
00704     IACglobals.event = event; 
00705     
00706     if (!IACpushRGBColorparam (&rgb, 'colr'))
00707         return (false);
00708     
00709     return (true);
00710     } /*getcolorattributes*/
00711     
00712     
00713 static boolean setcolorattributes (hdlobject h, AppleEvent *event) {
00714     
00715     hdlcolordata hdata = (hdlcolordata) (**h).objectdata;   
00716     RGBColor rgb;
00717     
00718     IACglobals.event = event; 
00719     
00720     IACglobals.nextparamoptional = true;
00721     
00722     if (IACgetRGBColorparam ('colr', &rgb))
00723         (**hdata).rgb = rgb;
00724     
00725     return (true);
00726     } /*setcolorattributes*/
00727     
00728     
00729 static boolean recalccolorpopup (hdlobject h, boolean flmajorrecalc) {
00730 #pragma unused(flmajorrecalc)
00731 
00732     bigstring errorstring;
00733     Handle hrgbvalue;
00734     
00735     if (!IOAevalscript (h, (**h).objectrecalcscript, &hrgbvalue, (**h).objectlanguage, errorstring))
00736         return (false);
00737         
00738     setcolorpopupvalue (h, hrgbvalue); /*also disposes of hrgbvalue*/
00739     
00740     return (true); 
00741     } /*recalccolorpopup*/
00742     
00743 
00744 void setupcolorpopup (tyioaconfigrecord *);
00745 
00746 
00747 void setupcolorpopup (tyioaconfigrecord *config) {
00748     
00749     IOAcopystring ("\pColor popup", (*config).objectTypeName);
00750     
00751     (*config).objectTypeID = colorpopuptype;
00752     
00753     (*config).frameWhenEditing = true;
00754     
00755     (*config).canEditValue = true;
00756     
00757     (*config).toggleFlagWhenHit = false;
00758     
00759     (*config).mutuallyExclusive = false;
00760     
00761     (*config).speaksForGroup = false;
00762     
00763     (*config).handlesMouseTrack = true; /*allow the popup manager to track the mouse*/
00764 
00765     (*config).hasSpecialCard = false; /*dmb 1.0b22 - was true, but there's no card*/
00766 
00767     (*config).initObjectCallback = initcolorpopup;
00768     
00769     (*config).drawObjectCallback = drawcolorobject;
00770     
00771     (*config).clickObjectCallback = clickcolorpopup;
00772     
00773     (*config).cleanupObjectCallback = cleancolorpopup;
00774     
00775     (*config).canReplicateObjectCallback = canreplicatecolorpopup;
00776     
00777     (*config).getObjectEditRectCallback = getcoloreditrect;
00778     
00779     (*config).getValueForScriptCallback = getcolorpopupvalue;
00780     
00781     (*config).debugObjectCallback = debugcolorpopup;    
00782     
00783     (*config).getAttributesCallback = getcolorattributes;
00784     
00785     (*config).setAttributesCallback = setcolorattributes;
00786     
00787     (*config).unpackDataCallback = unpackcolordata;
00788     
00789     (*config).recalcObjectCallback = recalccolorpopup;
00790     } /*setupconfig*/
00791     
00792     

Generated on Wed May 31 18:19:49 2006 for frontierkernel 10.1.10a by  doxygen 1.4.6