Changeset 191

Show
Ignore:
Timestamp:
07/03/10 21:58:03 (2 years ago)
Author:
JoeCoder
Message:

Added css style inheritance and auto properties to yage.gui.style
Created Surface.getComputedStyle() to get styles in terms of pixels and replause "auto" with inherited values.
Reworked Surface.updateDimensions to work off of the new getComputedStyle()

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/src/demo2/main.d

    r183 r191  
    6666    info.style.set("top: 40px; left: 40px; width: 500px; height: 260px; padding: 3px; color: brown; " ~ 
    6767        "border-width: 5px; border-image: url('gui/skin/clear2.png'); " ~ 
    68         "font: 14px url('Vera.ttf'); text-align: right; opacity: .8; overflow: hidden"); 
     68        "font-family: url('Vera.ttf'); text-align: right; opacity: .8; overflow: hidden"); 
    6969    info.style.overflowX = Style.Overflow.HIDDEN; 
    7070    info.style.overflowY = Style.Overflow.HIDDEN; 
  • trunk/src/tests/integration/main.d

    r189 r191  
    7575     
    7676    void keyState(int key, bool state) 
    77     {   if (key == SDLK_w
     77    {   if (key == SDLK_w || key == SDLK_UP
    7878            camera.up = state; 
    79         if (key == SDLK_a
     79        if (key == SDLK_a || key == SDLK_LEFT
    8080            camera.left = state; 
    81         if (key == SDLK_s
     81        if (key == SDLK_s || key == SDLK_DOWN
    8282            camera.down = state; 
    83         if (key == SDLK_d
     83        if (key == SDLK_d || key == SDLK_RIGHT
    8484            camera.right = state; 
    8585         
     
    135135        l4.setPosition(Vec3f(-100, 0, 0)); 
    136136        l4.setLightRadius(100); 
    137         l4.diffuse = "blue"; 
    138          
    139          
     137        l4.diffuse = "blue";         
     138         
     139        //camera.setPosition(Vec3f(0, 0, -500)); 
     140    } 
     141
     142 
     143class Picking : TestScene 
     144
     145    Model asteroid; 
     146     
     147    this() 
     148    { 
     149        int length = 4; 
     150        int spacing = 150; 
     151         
     152        // Add asteroids 
     153        asteroid = new Model("space/asteroid1.dae"); 
     154        for (int x=-length/2; x<length/2; x++) 
     155            for (int y=-length/2; y<length/2; y++) 
     156                for (int z=-length/2; z<length/2; z++) 
     157                {   auto node = new ModelNode(asteroid); 
     158                    node.setPosition(Vec3f(x*spacing, y*spacing, z*spacing)); 
     159                    node.setScale(Vec3f(random(.2, 5))); 
     160                    addChild(node); 
     161                } 
     162         
     163        // Add rotating lights 
     164        LightNode l = addChild(new LightNode()); 
     165        l.setPosition(Vec3f(30, 30, 130)); 
     166        l.setLightRadius(400); 
     167             
    140168        //camera.setPosition(Vec3f(0, 0, -500)); 
    141169    } 
     
    391419 
    392420    // Create and start a Scene 
    393     auto scene = new LightsAndFog(); // set which scene to test 
     421    auto scene = new Picking(); // set which scene to test 
    394422    scene.getUpdateThread().setFrequency(60); 
    395423    scene.play(); // start scene thread 
  • trunk/src/yage/core/format.d

    r177 r191  
    88 * This behaves exactly the same as writef, but returns a string instead of printing it.  
    99 * It can also accept the _arguments, and _argptr directly from another var arg function. 
    10  * It would be nice to have this functionality in less than 1600 lines of code. */ 
     10 * It would be nice to have this functionality in less than 1300 lines of code. */ 
    1111char[] swritef(...) 
    1212{    
     
    4949 * 
    5050 *  o  The origin of this software must not be misrepresented; you must not 
    51  *    claim that you wrote the original software. If you use this software 
    52  *    in a product, an acknowledgment in the product documentation would be 
    53  *    appreciated but is not required. 
     51 * claim that you wrote the original software. If you use this software 
     52 * in a product, an acknowledgment in the product documentation would be 
     53 * appreciated but is not required. 
    5454 *  o  Altered source versions must be plainly marked as such, and must not 
    55  *    be misrepresented as being the original software. 
     55 * be misrepresented as being the original software. 
    5656 *  o  This notice may not be removed or altered from any source 
    57  *    distribution. 
     57 * distribution. 
    5858 */ 
    5959 
     
    6767import tango.core.Exception; 
    6868 
    69 //Had to add this for tangobos. 
    70 private T va_arg2(T)(inout void* _argptr) 
    71 { 
    72     version(DigitalMars) { 
    73         T arg = *cast(T*)_argptr; 
    74         _argptr = _argptr + ((T.sizeof + int.sizeof - 1) & ~(int.sizeof - 1)); 
    75         return arg; 
    76     } else { 
    77         T t; return t; 
    78     } 
    79 } 
    80  
    81  
    82  
    8369version (Windows) 
    8470{ 
    85     version (DigitalMars) 
    86    
    87       version = DigitalMarsC; 
    88    
    89     version (GNU) 
    90    
    91       version = GNU_MinGW_MSVCRT; 
    92    
     71   version (DigitalMars) 
     72   
     73      version = DigitalMarsC; 
     74   
     75   version (GNU) 
     76   
     77      version = GNU_MinGW_MSVCRT; 
     78   
    9379} 
    9480 
    9581version (DigitalMarsC) 
    9682{ 
    97     // This is DMC's internal floating point formatting function 
    98     extern (C) 
    99     {     extern char* function(int c, int flags, int precision, real* pdval, 
    100         char* buf, int* psl, int width) __pfloatfmt; 
    101    
     83   // This is DMC's internal floating point formatting function 
     84   extern (C) 
     85   {      extern char* function(int c, int flags, int precision, real* pdval, 
     86       char* buf, int* psl, int width) __pfloatfmt; 
     87   
    10288} 
    10389else 
    10490{ 
    105     // Use C99 snprintf 
    106     extern (C) int snprintf(char* s, size_t n, char* format, ...); 
     91   // Use C99 snprintf 
     92   extern (C) int snprintf(char* s, size_t n, char* format, ...); 
    10793} 
    10894 
     
    11298class FormatError : Exception 
    11399{   this() 
    114     {     super("yage.core.format"); 
    115    
    116  
    117     this(char[] msg) 
    118     { super("yage.core.format " ~ msg); 
    119    
     100   {      super("yage.core.format"); 
     101   
     102 
     103   this(char[] msg) 
     104   {  super("yage.core.format " ~ msg); 
     105   
    120106} 
    121107 
     
    123109private enum Mangle : char 
    124110{ 
    125     Tvoid    = 'v', 
    126     Tbool    = 'b', 
    127     Tbyte    = 'g', 
    128     Tubyte    = 'h', 
    129     Tshort    = 's', 
    130     Tushort   = 't', 
    131     Tint      = 'i', 
    132     Tuint    = 'k', 
    133     Tlong    = 'l', 
    134     Tulong    = 'm', 
    135     Tfloat    = 'f', 
    136     Tdouble   = 'd', 
    137     Treal    = 'e', 
    138  
    139     Tifloat   = 'o', 
    140     Tidouble  = 'p', 
    141     Tireal    = 'j', 
    142     Tcfloat   = 'q', 
    143     Tcdouble  = 'r', 
    144     Tcreal    = 'c', 
    145  
    146     Tchar    = 'a', 
    147     Twchar    = 'u', 
    148     Tdchar    = 'w', 
    149  
    150     Tarray    = 'A', 
    151     Tsarray   = 'G', 
    152     Taarray   = 'H', 
    153     Tpointer  = 'P', 
    154     Tfunction = 'F', 
    155     Tident    = 'I', 
    156     Tclass    = 'C', 
    157     Tstruct   = 'S', 
    158     Tenum    = 'E', 
    159     Ttypedef  = 'T', 
    160     Tdelegate = 'D', 
    161  
    162     Tconst    = 'x', 
    163     Tinvariant = 'y', 
     111   Tvoid    = 'v', 
     112   Tbool    = 'b', 
     113   Tbyte    = 'g', 
     114   Tubyte  = 'h', 
     115   Tshort  = 's', 
     116   Tushort   = 't', 
     117   Tint      = 'i', 
     118   Tuint    = 'k', 
     119   Tlong    = 'l', 
     120   Tulong  = 'm', 
     121   Tfloat  = 'f', 
     122   Tdouble   = 'd', 
     123   Treal    = 'e', 
     124 
     125   Tifloat   = 'o', 
     126   Tidouble  = 'p', 
     127   Tireal  = 'j', 
     128   Tcfloat   = 'q', 
     129   Tcdouble  = 'r', 
     130   Tcreal  = 'c', 
     131 
     132   Tchar    = 'a', 
     133   Twchar  = 'u', 
     134   Tdchar  = 'w', 
     135 
     136   Tarray  = 'A', 
     137   Tsarray   = 'G', 
     138   Taarray   = 'H', 
     139   Tpointer  = 'P', 
     140   Tfunction = 'F', 
     141   Tident  = 'I', 
     142   Tclass  = 'C', 
     143   Tstruct   = 'S', 
     144   Tenum    = 'E', 
     145   Ttypedef  = 'T', 
     146   Tdelegate = 'D', 
     147 
     148   Tconst  = 'x', 
     149   Tinvariant = 'y', 
    164150} 
    165151 
     
    200186private void doFormatPtr(void delegate(dchar) putc, TypeInfo[] arguments,  void* argptr, void* p_args) 
    201187{   int j; 
    202     TypeInfo ti; 
    203     Mangle m; 
    204     uint flags; 
    205     int field_width; 
    206     int precision; 
    207  
    208     enum : uint 
    209    
     188   TypeInfo ti; 
     189   Mangle m; 
     190   uint flags; 
     191   int field_width; 
     192   int precision; 
     193 
     194   enum : uint 
     195   
    210196        FLdash = 1, 
    211197        FLplus = 2, 
     
    215201        FL0pad = 0x40, 
    216202        FLprecision = 0x80, 
    217     } 
    218  
    219     void formatArg(char fc) 
    220     { 
    221     bool vbit; 
    222     ulong vnumber; 
    223     char vchar; 
    224     dchar vdchar; 
    225     Object vobject; 
    226     real vreal; 
    227     creal vcreal; 
    228     Mangle m2; 
    229     int signed = 0; 
    230     uint base = 10; 
    231     int uc; 
    232     char[ulong.sizeof * 8] tmpbuf;  // long enough to print long in binary 
    233     char* prefix = ""; 
    234     string s; 
    235  
    236     void putstr(char[] s) 
     203    } 
     204 
     205    void formatArg(char fc) 
    237206    { 
    238         //printf("flags = x%x\n", flags); 
    239         int prepad = 0; 
    240         int postpad = 0; 
    241         int padding = field_width - (strlen(prefix) + s.length); 
    242         if (padding > 0) 
    243         { 
    244         if (flags & FLdash) 
    245             postpad = padding; 
     207        bool vbit; 
     208        ulong vnumber; 
     209        char vchar; 
     210        dchar vdchar; 
     211        Object vobject; 
     212        real vreal; 
     213        creal vcreal; 
     214        Mangle m2; 
     215        int signed = 0; 
     216        uint base = 10; 
     217        int uc; 
     218        char[ulong.sizeof * 8] tmpbuf;  // long enough to print long in binary 
     219        char* prefix = ""; 
     220        string s; 
     221     
     222        void putstr(char[] s) 
     223        { 
     224            //printf("flags = x%x\n", flags); 
     225            int prepad = 0; 
     226            int postpad = 0; 
     227            int padding = field_width - (strlen(prefix) + s.length); 
     228            if (padding > 0) 
     229            { 
     230                if (flags & FLdash) 
     231                    postpad = padding; 
     232                else 
     233                    prepad = padding; 
     234            } 
     235     
     236            if (flags & FL0pad) 
     237            { 
     238                while (*prefix) 
     239                    putc(*prefix++); 
     240                while (prepad--) 
     241                    putc('0'); 
     242            } 
     243            else 
     244            { 
     245                while (prepad--) 
     246                    putc(' '); 
     247                while (*prefix) 
     248                    putc(*prefix++); 
     249            } 
     250             
     251            try { 
     252                foreach (dchar c; s) 
     253                    putc(c); 
     254            } catch (UnicodeException e) 
     255            {   foreach (char c; s) 
     256                    putc(c); 
     257            } 
     258     
     259            while (postpad--) 
     260            putc(' '); 
     261        } 
     262     
     263        void putreal(real v) 
     264        { 
     265            //printf("putreal %Lg\n", vreal); 
     266     
     267            switch (fc) 
     268            { 
     269            case 's': 
     270                fc = 'g'; 
     271                break; 
     272     
     273            case 'f', 'F', 'e', 'E', 'g', 'G', 'a', 'A': 
     274                break; 
     275     
     276            default: 
     277                //printf("fc = '%c'\n", fc); 
     278            Lerror: 
     279                throw new FormatError("floating"); 
     280            } 
     281            version (DigitalMarsC) 
     282            { 
     283                int sl; 
     284                char[] fbuf = tmpbuf; 
     285                if (!(flags & FLprecision)) 
     286                    precision = 6; 
     287                while (1) 
     288                { 
     289                    sl = fbuf.length; 
     290                    prefix = (*__pfloatfmt)(fc, flags | FLlngdbl, 
     291                        precision, &v, cast(char*)fbuf, &sl, field_width); 
     292                    if (sl != -1) 
     293                    break; 
     294                    sl = fbuf.length * 2; 
     295                    fbuf = (cast(char*)alloca(sl * char.sizeof))[0 .. sl]; 
     296                } 
     297                putstr(fbuf[0 .. sl]); 
     298            } 
     299            else 
     300            { 
     301                int sl; 
     302                char[] fbuf = tmpbuf; 
     303                char[12] format; 
     304                format[0] = '%'; 
     305                int i = 1; 
     306                if (flags & FLdash) 
     307                    format[i++] = '-'; 
     308                if (flags & FLplus) 
     309                    format[i++] = '+'; 
     310                if (flags & FLspace) 
     311                    format[i++] = ' '; 
     312                if (flags & FLhash) 
     313                    format[i++] = '#'; 
     314                if (flags & FL0pad) 
     315                    format[i++] = '0'; 
     316                format[i + 0] = '*'; 
     317                format[i + 1] = '.'; 
     318                format[i + 2] = '*'; 
     319                i += 3; 
     320                version (GNU_MinGW_MSVCRT) 
     321                    { /* nothing: no support for long double */ } 
     322                else 
     323                    static if (real.sizeof > double.sizeof) 
     324                    format[i++] = 'L'; 
     325                format[i++] = fc; 
     326                format[i] = 0; 
     327                if (!(flags & FLprecision)) 
     328                    precision = -1; 
     329                while (1) 
     330                {   int n; 
     331         
     332                    sl = fbuf.length; 
     333                    version (GNU_MinGW_MSVCRT) 
     334                    n = snprintf(fbuf.ptr, sl, format.ptr, field_width, precision, cast(double) v); 
     335                    else 
     336                    n = snprintf(fbuf.ptr, sl, format.ptr, field_width, precision, v); 
     337                    //printf("format = '%s', n = %d\n", cast(char*)format, n); 
     338                    if (n >= 0 && n < sl) 
     339                    {   sl = n; 
     340                    break; 
     341                    } 
     342                    if (n < 0) 
     343                    sl = sl * 2; 
     344                    else 
     345                    sl = n + 1; 
     346                    fbuf = (cast(char*)alloca(sl * char.sizeof))[0 .. sl]; 
     347                } 
     348                putstr(fbuf[0 .. sl]); 
     349            } 
     350            return; 
     351        } 
     352     
     353        static Mangle getMan(TypeInfo ti) 
     354        { 
     355            auto m = cast(Mangle)ti.classinfo.name[9]; 
     356            if (ti.classinfo.name.length == 20 && 
     357                ti.classinfo.name[9..20] == "StaticArray") 
     358            m = cast(Mangle)'G'; 
     359                return m; 
     360        } 
     361     
     362        void putArray(void* p, size_t len, TypeInfo valti) 
     363        { 
     364          putc('['); 
     365          size_t tsize = valti.tsize(); 
     366          version(DigitalMars) 
     367            auto argptrSave = argptr; 
     368          else 
     369              auto argptrSave = p_args; 
     370          auto tiSave = ti; 
     371          auto mSave = m; 
     372          ti = valti; 
     373          m = getMan(valti); 
     374          while (len--) 
     375          { 
     376            version (DigitalMars) 
     377                argptr = cast(void*) p; 
     378            else 
     379                p_args = p; 
     380            formatArg('s'); 
     381     
     382            p += tsize; 
     383            if (len > 0) putc(','); 
     384          } 
     385          m = mSave; 
     386          ti = tiSave; 
     387          version (DigitalMars) 
     388            argptr = argptrSave; 
     389          else 
     390            p_args = argptrSave; 
     391          putc(']'); 
     392        } 
     393     
     394        void putAArray(ubyte[long] vaa, TypeInfo valti, TypeInfo keyti) 
     395        { 
     396            // Copied from aaA.d 
     397            size_t aligntsize(size_t tsize) 
     398            { 
     399            // Is pointer alignment on the x64 4 bytes or 8? 
     400            return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1); 
     401            } 
     402             
     403          putc('['); 
     404          bool comma=false; 
     405          version (DigitalMars) 
     406            auto argptrSave = argptr; 
     407          else 
     408            auto argptrSave = p_args; 
     409          auto tiSave = ti; 
     410          auto mSave = m; 
     411          foreach(inout fakevalue; vaa) 
     412          { 
     413            if (comma) putc(','); 
     414            comma = true; 
     415            // the key comes before the value 
     416            ubyte* key = &fakevalue - long.sizeof; 
     417     
     418            version (DigitalMars) 
     419                argptr = cast(void*) key; 
     420            else 
     421                p_args = key; 
     422            ti = keyti; 
     423            m = getMan(keyti); 
     424            formatArg('s'); 
     425     
     426            putc(':'); 
     427            ubyte* value = key + aligntsize(keyti.tsize); 
     428            version (DigitalMars) 
     429                argptr = cast(void*) value; 
     430            else 
     431                p_args = value; 
     432            ti = valti; 
     433            m = getMan(valti); 
     434            formatArg('s'); 
     435          } 
     436          m = mSave; 
     437          ti = tiSave; 
     438          version (DigitalMars) 
     439            argptr = argptrSave; 
     440          else 
     441            p_args = argptrSave; 
     442          putc(']'); 
     443        } 
     444     
     445        if (! p_args) { 
     446        switch (m) 
     447        { 
     448            case Mangle.Tbool: 
     449            vbit = va_arg!(bool)(argptr); 
     450            if (fc != 's') 
     451            {   vnumber = vbit; 
     452                goto Lnumber; 
     453            } 
     454            putstr(vbit ? "true" : "false"); 
     455            return; 
     456     
     457            case Mangle.Tchar: 
     458            vchar = va_arg!(char)(argptr); 
     459            if (fc != 's') 
     460            {   vnumber = vchar; 
     461                goto Lnumber; 
     462            } 
     463            L2: 
     464            putstr((&vchar)[0 .. 1]); 
     465            return; 
     466     
     467            case Mangle.Twchar: 
     468            vdchar = va_arg!(wchar)(argptr); 
     469            goto L1; 
     470     
     471            case Mangle.Tdchar: 
     472            vdchar = va_arg!(dchar)(argptr); 
     473            L1: 
     474            if (fc != 's') 
     475            {   vnumber = vdchar; 
     476                goto Lnumber; 
     477            } 
     478            if (vdchar <= 0x7F) 
     479            {   vchar = cast(char)vdchar; 
     480                goto L2; 
     481            } 
     482            else 
     483            {   if (!isValid(vdchar)) 
     484                throw new Exception("invalid dchar in format"); 
     485                putstr(.toString([vdchar])); 
     486            } 
     487            return; 
     488     
     489            case Mangle.Tbyte: 
     490            signed = 1; 
     491            vnumber = va_arg!(byte)(argptr); 
     492            goto Lnumber; 
     493     
     494            case Mangle.Tubyte: 
     495            vnumber = va_arg!(ubyte)(argptr); 
     496            goto Lnumber; 
     497     
     498            case Mangle.Tshort: 
     499            signed = 1; 
     500            vnumber = va_arg!(short)(argptr); 
     501            goto Lnumber; 
     502     
     503            case Mangle.Tushort: 
     504            vnumber = va_arg!(ushort)(argptr); 
     505            goto Lnumber; 
     506     
     507            case Mangle.Tint: 
     508            signed = 1; 
     509            vnumber = va_arg!(int)(argptr); 
     510            goto Lnumber; 
     511     
     512            case Mangle.Tuint: 
     513            Luint: 
     514            vnumber = va_arg!(uint)(argptr); 
     515            goto Lnumber; 
     516     
     517            case Mangle.Tlong: 
     518            signed = 1; 
     519            vnumber = cast(ulong)va_arg!(long)(argptr); 
     520            goto Lnumber; 
     521     
     522            case Mangle.Tulong: 
     523            Lulong: 
     524            vnumber = va_arg!(ulong)(argptr); 
     525            goto Lnumber; 
     526     
     527            case Mangle.Tclass: 
     528            vobject = va_arg!(Object)(argptr); 
     529            if (vobject is null) 
     530                s = "null"; 
     531            else 
     532                s = vobject.toString(); 
     533            goto Lputstr; 
     534     
     535            case Mangle.Tpointer: 
     536            vnumber = cast(size_t)va_arg!(void*)(argptr); 
     537            uc = 1; 
     538            flags |= FL0pad; 
     539            if (!(flags & FLprecision)) 
     540            {   flags |= FLprecision; 
     541                precision = (void*).sizeof; 
     542            } 
     543            base = 16; 
     544            goto Lnumber; 
     545     
     546            case Mangle.Tfloat: 
     547            case Mangle.Tifloat: 
     548            if (fc == 'x' || fc == 'X') 
     549            { 
     550                version (DigitalMars) 
     551                    goto Luint; 
     552                else { 
     553                    float f = va_arg!(float)(argptr); 
     554                    vnumber = *cast(uint*)&f; 
     555                    goto Lnumber; 
     556                } 
     557            } 
     558            vreal = va_arg!(float)(argptr); 
     559            goto Lreal; 
     560     
     561            case Mangle.Tdouble: 
     562            case Mangle.Tidouble: 
     563            if (fc == 'x' || fc == 'X') 
     564            { 
     565                version (DigitalMars) 
     566                    goto Lulong; 
     567                else { 
     568                    double f = va_arg!(double)(argptr); 
     569                    vnumber = *cast(ulong*)&f; 
     570                    goto Lnumber; 
     571                } 
     572            } 
     573            vreal = va_arg!(double)(argptr); 
     574            goto Lreal; 
     575     
     576            case Mangle.Treal: 
     577            case Mangle.Tireal: 
     578            vreal = va_arg!(real)(argptr); 
     579            goto Lreal; 
     580     
     581            case Mangle.Tcfloat: 
     582            vcreal = va_arg!(cfloat)(argptr); 
     583            goto Lcomplex; 
     584     
     585            case Mangle.Tcdouble: 
     586            vcreal = va_arg!(cdouble)(argptr); 
     587            goto Lcomplex; 
     588     
     589            case Mangle.Tcreal: 
     590            vcreal = va_arg!(creal)(argptr); 
     591            goto Lcomplex; 
     592     
     593            case Mangle.Tsarray: 
     594            version (DigitalMars) { 
     595                putArray(argptr, (cast(TypeInfo_StaticArray)ti).len, (cast(TypeInfo_StaticArray)ti).next); 
     596                return; 
     597            } 
     598            version (GNU) { 
     599            /* Static arrays are converted to dynamic arrays when 
     600               passed as a variadic argument, so this code should 
     601               never be executed with GDC.  The case of an 
     602               embedded static array is handled below. */ 
     603               goto Lerror; 
     604            } 
     605     
     606            case Mangle.Tarray: 
     607            int mi = 10; 
     608            if (ti.classinfo.name.length == 14 && ti.classinfo.name[9..14] == "Array")  
     609            { // array of non-primitive types 
     610              TypeInfo tn = (cast(TypeInfo_Array)ti).next; 
     611              switch (cast(Mangle)tn.classinfo.name[9]) 
     612              { 
     613                case Mangle.Tchar:  goto LarrayChar; 
     614                case Mangle.Twchar: goto LarrayWchar; 
     615                case Mangle.Tdchar: goto LarrayDchar; 
     616                default: 
     617                break; 
     618              } 
     619              void[] va = va_arg!(void[])(argptr); 
     620              putArray(va.ptr, va.length, tn); 
     621              return; 
     622            } 
     623            if (ti.classinfo.name.length == 25 && 
     624                ti.classinfo.name[9..25] == "AssociativeArray")  
     625            { // associative array 
     626              ubyte[long] vaa = va_arg!(ubyte[long])(argptr); 
     627              putAArray(vaa, 
     628                (cast(TypeInfo_AssociativeArray)ti).next, 
     629                (cast(TypeInfo_AssociativeArray)ti).key); 
     630              return; 
     631            } 
     632     
     633            while (1) 
     634            { 
     635                m2 = cast(Mangle)ti.classinfo.name[mi]; 
     636                switch (m2) 
     637                { 
     638                case Mangle.Tchar: 
     639                LarrayChar: 
     640                    s = va_arg!(char[])(argptr); 
     641                    goto Lputstr; 
     642     
     643                case Mangle.Twchar: 
     644                LarrayWchar: 
     645                    wchar[] sw = va_arg!(wchar[])(argptr); 
     646                    s = .toString(sw); 
     647                    goto Lputstr; 
     648     
     649                case Mangle.Tdchar: 
     650                LarrayDchar: 
     651                    dchar[] sd = va_arg!(dchar[])(argptr); 
     652                    s = .toString(sd); 
     653                Lputstr: 
     654                    if (fc != 's') 
     655                    throw new FormatError("string"); 
     656                    if (flags & FLprecision && precision < s.length) 
     657                    s = s[0 .. precision]; 
     658                    putstr(s); 
     659                    break; 
     660     
     661                case Mangle.Tconst: 
     662                case Mangle.Tinvariant: 
     663                    mi++; 
     664                    continue; 
     665     
     666                default: 
     667                    TypeInfo ti2 = primitiveTypeInfo(m2); 
     668                    if (!ti2) 
     669                        throw new FormatError("Can't get type info for type " ~ cast(char)m2); 
     670                    void[] va = va_arg!(void[])(argptr); 
     671                    putArray(va.ptr, va.length, ti2); 
     672                } 
     673                return; 
     674            } 
     675            case Mangle.Ttypedef: 
     676            ti = (cast(TypeInfo_Typedef)ti).base; 
     677            m = cast(Mangle)ti.classinfo.name[9]; 
     678            formatArg(fc); 
     679            return; 
     680     
     681            case Mangle.Tenum: 
     682            ti = (cast(TypeInfo_Enum)ti).base; 
     683            m = cast(Mangle)ti.classinfo.name[9]; 
     684            formatArg(fc); 
     685            return; 
     686     
     687            case Mangle.Tstruct: 
     688            {   TypeInfo_Struct tis = cast(TypeInfo_Struct)ti; 
     689                if (tis.xtoString is null) 
     690                    throw new FormatError("Can't convert " ~ tis.toString() ~ " to string: \"string toString()\" not defined"); 
     691                version(DigitalMars){ 
     692                     
     693                    char[] delegate() toString; 
     694                    toString.ptr = argptr; 
     695                    toString.funcptr = cast(char[] function())tis.xtoString;  
     696                    s = Utf.fromString8 (toString(), s);                 
     697                    // s = tis.xtoString(argptr); 
     698                     
     699                    argptr += (tis.tsize() + 3) & ~3; 
     700                } 
     701                version (GNU){ 
     702                static if (is( typeof(argptr): void[] ) ||  is( typeof(argptr) == struct )) 
     703                { 
     704                    version(PPC) 
     705                    { 
     706                        // Structs are pass-by-reference in V4 ABI 
     707                        s = tis.xtoString(va_arg!(void*)(argptr)); 
     708                    } 
     709                    else version(X86_64) 
     710                    { 
     711                        throw new FormatError("cannot portably format a struct on this target"); 
     712                    } 
     713                    else 
     714                    { 
     715                        static assert(0, "unimplemented"); 
     716                    } 
     717                } 
     718                else 
     719                { 
     720                    s = tis.xtoString(argptr); 
     721                    argptr += (tis.tsize() + 3) & ~3; // this looks like it should call aligntsize 
     722                } 
     723            } 
     724            goto Lputstr; 
     725            } 
     726     
     727            default: 
     728                if (m2=='v') 
     729                    throw new FormatError("Can't get type info for type void"); 
     730                else 
     731                    throw new FormatError("Can't get type info for mangled type " ~ cast(char)m2); 
     732        }} 
    246733        else 
    247             prepad = padding; 
    248         } 
    249  
    250         if (flags & FL0pad) 
    251         { 
    252         while (*prefix) 
    253             putc(*prefix++); 
    254         while (prepad--) 
    255             putc('0'); 
    256         } 
    257         else 
    258         { 
    259         while (prepad--) 
    260             putc(' '); 
    261         while (*prefix) 
    262             putc(*prefix++); 
    263         } 
    264          
    265         try { 
    266             foreach (dchar c; s) 
    267                 putc(c); 
    268         } catch (UnicodeException e) 
    269         {   foreach (char c; s) 
    270                 putc(c); 
    271         } 
    272  
    273         while (postpad--) 
    274         putc(' '); 
     734        { 
     735            version (DigitalMars) assert(0); 
     736            switch (m) 
     737            { 
     738            case Mangle.Tbool: 
     739                vbit = *cast(bool*)(p_args); p_args += bool.sizeof; // int.sizeof, etc.? 
     740                if (fc != 's') 
     741                {   vnumber = vbit; 
     742                goto Lnumber; 
     743                } 
     744                putstr(vbit ? "true" : "false"); 
     745                return; 
     746         
     747         
     748            case Mangle.Tchar: 
     749                vchar = *cast(char*)(p_args); p_args += char.sizeof; 
     750                if (fc != 's') 
     751                {   vnumber = vchar; 
     752                goto Lnumber; 
     753                } 
     754            PL2: // there is goto L2 outside of thise switch; it's okay to do that 
     755                putstr((&vchar)[0 .. 1]); 
     756                return; 
     757         
     758            case Mangle.Twchar: 
     759                vdchar = *cast(wchar*)(p_args); p_args += wchar.sizeof; 
     760                goto PL1; 
     761         
     762            case Mangle.Tdchar: 
     763                vdchar = *cast(dchar*)(p_args); p_args += dchar.sizeof; 
     764            PL1: 
     765                if (fc != 's') 
     766                {   vnumber = vdchar; 
     767                    goto Lnumber; 
     768                } 
     769                if (vdchar <= 0x7F) 
     770                {   vchar = cast(char)vdchar; 
     771                    goto PL2; 
     772                } 
     773                else 
     774                {   if (!isValid(vdchar)) 
     775                    throw new Exception("invalid dchar in format"); 
     776                    putstr(.toString([vdchar])); 
     777                } 
     778                return; 
     779         
     780         
     781            case Mangle.Tbyte: 
     782                signed = 1; 
     783                vnumber = *cast(byte*)p_args; p_args += byte.sizeof; 
     784                goto Lnumber; 
     785         
     786            case Mangle.Tubyte: 
     787                vnumber = *cast(ubyte*)p_args; p_args += ubyte.sizeof; 
     788                goto Lnumber; 
     789         
     790            case Mangle.Tshort: 
     791                signed = 1; 
     792                vnumber = *cast(short*)p_args; p_args += short.sizeof; 
     793                goto Lnumber; 
     794         
     795            case Mangle.Tushort: 
     796                vnumber = *cast(ushort*)p_args; p_args += ushort.sizeof; 
     797                goto Lnumber; 
     798         
     799            case Mangle.Tint: 
     800                signed = 1; 
     801                vnumber = *cast(int*)p_args; p_args += int.sizeof; 
     802                goto Lnumber; 
     803         
     804            case Mangle.Tuint: 
     805            PLuint: 
     806                vnumber = *cast(uint*)p_args; p_args += uint.sizeof; 
     807                goto Lnumber; 
     808         
     809            case Mangle.Tlong: 
     810                signed = 1; 
     811                vnumber = cast(ulong)*cast(long*)p_args; p_args += long.sizeof; 
     812                goto Lnumber; 
     813         
     814            case Mangle.Tulong: 
     815            PLulong: 
     816                vnumber = *cast(ulong*)p_args; p_args += ulong.sizeof; 
     817                goto Lnumber; 
     818         
     819            case Mangle.Tclass: 
     820                vobject = *cast(Object*)p_args; p_args += Object.sizeof; 
     821                s = vobject.toString(); 
     822                goto Lputstr; 
     823         
     824            case Mangle.Tpointer: 
     825                alias void * void_ponter_t; 
     826                vnumber = cast(size_t)*cast(void**)p_args; p_args += void_ponter_t.sizeof; 
     827                uc = 1; 
     828                flags |= FL0pad; 
     829                if (!(flags & FLprecision)) 
     830                {   flags |= FLprecision; 
     831                    precision = (void*).sizeof; 
     832                } 
     833                base = 16; 
     834                goto Lnumber; 
     835         
     836         
     837            case Mangle.Tfloat: 
     838            case Mangle.Tifloat: 
     839                if (fc == 'x' || fc == 'X') 
     840                goto PLuint; 
     841                vreal = *cast(float*)p_args; p_args += float.sizeof; 
     842                goto Lreal; 
     843         
     844            case Mangle.Tdouble: 
     845            case Mangle.Tidouble: 
     846                if (fc == 'x' || fc == 'X') 
     847                goto PLulong; 
     848                vreal = *cast(double*)p_args; p_args += double.sizeof; 
     849                goto Lreal; 
     850         
     851            case Mangle.Treal: 
     852            case Mangle.Tireal: 
     853                vreal = *cast(real*)p_args; p_args += real.sizeof; 
     854                goto Lreal; 
     855         
     856         
     857            case Mangle.Tcfloat: 
     858                vcreal = *cast(cfloat*)p_args; p_args += cfloat.sizeof; 
     859                goto Lcomplex; 
     860         
     861            case Mangle.Tcdouble: 
     862                vcreal = *cast(cdouble*)p_args; p_args += cdouble.sizeof; 
     863                goto Lcomplex; 
     864         
     865            case Mangle.Tcreal: 
     866                vcreal = *cast(creal*)p_args; p_args += creal.sizeof; 
     867                goto Lcomplex; 
     868         
     869            case Mangle.Tsarray: 
     870                putArray(p_args, (cast(TypeInfo_StaticArray)ti).len, (cast(TypeInfo_StaticArray)ti).next); 
     871                p_args += ti.tsize(); 
     872                return; 
     873     
     874            case Mangle.Tarray: 
     875                alias void[] array_t; 
     876                int mi = 10; 
     877                if (ti.classinfo.name.length == 14 && 
     878                ti.classinfo.name[9..14] == "Array")  
     879                { // array of non-primitive types 
     880                  TypeInfo tn = (cast(TypeInfo_Array)ti).next; 
     881                  switch (cast(Mangle)tn.classinfo.name[9]) 
     882                  { 
     883                case Mangle.Tchar:  goto LarrayChar_p; 
     884                case Mangle.Twchar: goto LarrayWchar_p; 
     885                case Mangle.Tdchar: goto LarrayDchar_p; 
     886                default: 
     887                    break; 
     888                  } 
     889                  void[] va = *cast(void[]*)p_args; p_args += array_t.sizeof; 
     890                  putArray(va.ptr, va.length, tn); 
     891                  return; 
     892                } 
     893                if (ti.classinfo.name.length == 25 && 
     894                ti.classinfo.name[9..25] == "AssociativeArray")  
     895                { // associative array 
     896                  ubyte[long] vaa = *cast(ubyte[long]*)p_args; p_args += vaa.sizeof; 
     897                  putAArray(vaa, 
     898                    (cast(TypeInfo_AssociativeArray)ti).next, 
     899                    (cast(TypeInfo_AssociativeArray)ti).key); 
     900                  return; 
     901                } 
     902     
     903                while (1) 
     904                { 
     905                m2 = cast(Mangle)ti.classinfo.name[mi]; 
     906                switch (m2) 
     907                { 
     908                    case Mangle.Tchar: 
     909                    LarrayChar_p: 
     910                    s = *cast(char[]*)p_args; p_args += array_t.sizeof; 
     911                    goto PLputstr; 
     912     
     913                    case Mangle.Twchar: 
     914                    LarrayWchar_p: 
     915                    wchar[] sw = *cast(wchar[]*)p_args; p_args += array_t.sizeof; 
     916                    s = .toString(sw); 
     917                    goto PLputstr; 
     918     
     919                    case Mangle.Tdchar: 
     920                    LarrayDchar_p: 
     921                    dchar[] sd = *cast(dchar[]*)p_args; p_args += array_t.sizeof; 
     922                    s = .toString(sd); 
     923                    PLputstr: 
     924                    if (fc != 's') 
     925                        throw new FormatError("string"); 
     926                    if (flags & FLprecision && precision < s.length) 
     927                        s = s[0 .. precision]; 
     928                    putstr(s); 
     929                    break; 
     930     
     931                    case Mangle.Tconst: 
     932                    case Mangle.Tinvariant: 
     933                    mi++; 
     934                    continue; 
     935     
     936                    default: 
     937                    TypeInfo ti2 = primitiveTypeInfo(m2); 
     938                    if (!ti2) 
     939                        throw new FormatError("Can't get type info for type " ~ cast(char)m2); 
     940                    void[] va = *cast(void[]*)p_args; p_args += array_t.sizeof; 
     941                    putArray(va.ptr, va.length, ti2); 
     942                } 
     943                return; 
     944                } 
     945         
     946            case Mangle.Ttypedef: 
     947                ti = (cast(TypeInfo_Typedef)ti).base; 
     948                m = cast(Mangle)ti.classinfo.name[9]; 
     949                formatArg(fc); 
     950                return; 
     951         
     952            case Mangle.Tenum: 
     953                ti = (cast(TypeInfo_Enum)ti).base; 
     954                m = cast(Mangle)ti.classinfo.name[9]; 
     955                formatArg(fc); 
     956                return; 
     957                 
     958            case Mangle.Tstruct: 
     959            {   TypeInfo_Struct tis = cast(TypeInfo_Struct)ti; 
     960                if (tis.xtoString is null) 
     961                throw new FormatError("Can't convert " ~ tis.toString() ~ " to string: \"string toString()\" not defined"); 
     962                 
     963                 
     964                char[] delegate() toString; 
     965                toString.ptr = argptr; 
     966                toString.funcptr = cast(char[] function())tis.xtoString;  
     967                s = Utf.fromString8 (toString(), s); 
     968                // s = tis.xtoString(p_args); 
     969                 
     970                 
     971                 
     972                p_args += tis.tsize(); 
     973                goto Lputstr; 
     974            } 
     975     
     976            default: 
     977                throw new FormatError("Could not format mangled type " ~ cast(char)m); 
     978            } 
     979        } 
     980     
     981        Lnumber: 
     982            switch (fc) 
     983            { 
     984                case 's': 
     985                case 'd': 
     986                if (signed) 
     987                {   if (cast(long)vnumber < 0) 
     988                    {   prefix = "-"; 
     989                    vnumber = -vnumber; 
     990                    } 
     991                    else if (flags & FLplus) 
     992                    prefix = "+"; 
     993                    else if (flags & FLspace) 
     994                    prefix = " "; 
     995                } 
     996                break; 
     997         
     998                case 'b': 
     999                signed = 0; 
     1000                base = 2; 
     1001                break; 
     1002         
     1003                case 'o': 
     1004                signed = 0; 
     1005                base = 8; 
     1006                break; 
     1007         
     1008                case 'X': 
     1009                uc = 1; 
     1010                if (flags & FLhash && vnumber) 
     1011                    prefix = "0X"; 
     1012                signed = 0; 
     1013                base = 16; 
     1014                break; 
     1015         
     1016                case 'x': 
     1017                if (flags & FLhash && vnumber) 
     1018                    prefix = "0x"; 
     1019                signed = 0; 
     1020                base = 16; 
     1021                break; 
     1022         
     1023                default: 
     1024                    throw new FormatError("Could not format number of mangled type " ~ fc); 
     1025            } 
     1026         
     1027            if (!signed) 
     1028            { 
     1029                switch (m) 
     1030                { 
     1031                case Mangle.Tbyte: 
     1032                    vnumber &= 0xFF; 
     1033                    break; 
     1034         
     1035                case Mangle.Tshort: 
     1036                    vnumber &= 0xFFFF; 
     1037                    break; 
     1038         
     1039                case Mangle.Tint: 
     1040                    vnumber &= 0xFFFFFFFF; 
     1041                    break; 
     1042         
     1043                default: 
     1044                    break; 
     1045                } 
     1046            } 
     1047         
     1048            if (flags & FLprecision && fc != 'p') 
     1049                flags &= ~FL0pad; 
     1050         
     1051            if (vnumber < base) 
     1052            { 
     1053                if (vnumber == 0 && precision == 0 && flags & FLprecision && 
     1054                !(fc == 'o' && flags & FLhash)) 
     1055                { 
     1056                putstr(null); 
     1057                return; 
     1058                } 
     1059                if (precision == 0 || !(flags & FLprecision)) 
     1060                {   vchar = cast(char)('0' + vnumber); 
     1061                if (vnumber < 10) 
     1062                    vchar = cast(char)('0' + vnumber); 
     1063                else 
     1064                    vchar = cast(char)((uc ? 'A' - 10 : 'a' - 10) + vnumber); 
     1065                goto L2; 
     1066                } 
     1067            } 
     1068         
     1069            int n = tmpbuf.length; 
     1070            char c; 
     1071            int hexoffset = uc ? ('A' - ('9' + 1)) : ('a' - ('9' + 1)); 
     1072         
     1073            while (vnumber) 
     1074            { 
     1075                c = cast(char)((vnumber % base) + '0'); 
     1076                if (c > '9') 
     1077                c += hexoffset; 
     1078                vnumber /= base; 
     1079                tmpbuf[--n] = c; 
     1080            } 
     1081            if (tmpbuf.length - n < precision && precision < tmpbuf.length) 
     1082            { 
     1083                int m = tmpbuf.length - precision; 
     1084                tmpbuf[m .. n] = '0'; 
     1085                n = m; 
     1086            } 
     1087            else if (flags & FLhash && fc == 'o') 
     1088                prefix = "0"; 
     1089            putstr(tmpbuf[n .. tmpbuf.length]); 
     1090            return; 
     1091     
     1092        Lreal: 
     1093            putreal(vreal); 
     1094            return; 
     1095     
     1096        Lcomplex: 
     1097            putreal(vcreal.re); 
     1098            putc('+'); 
     1099            putreal(vcreal.im); 
     1100            putc('i'); 
     1101            return; 
     1102     
     1103        Lerror: 
     1104            throw new FormatError("formatArg"); 
    2751105    } 
    2761106 
    277     void putreal(real v) 
    278     { 
    279         //printf("putreal %Lg\n", vreal); 
    280  
    281         switch (fc) 
    282         { 
    283         case 's': 
    284             fc = 'g'; 
    285             break; 
    286  
    287         case 'f', 'F', 'e', 'E', 'g', 'G', 'a', 'A': 
    288             break; 
    289  
    290         default: 
    291             //printf("fc = '%c'\n", fc); 
    292         Lerror: 
    293             throw new FormatError("floating"); 
    294         } 
    295         version (DigitalMarsC) 
    296         { 
    297             int sl; 
    298             char[] fbuf = tmpbuf; 
    299             if (!(flags & FLprecision)) 
    300                 precision = 6; 
    301             while (1) 
    302             { 
    303                 sl = fbuf.length; 
    304                 prefix = (*__pfloatfmt)(fc, flags | FLlngdbl, 
    305                     precision, &v, cast(char*)fbuf, &sl, field_width); 
    306                 if (sl != -1) 
    307                 break; 
    308                 sl = fbuf.length * 2; 
    309                 fbuf = (cast(char*)alloca(sl * char.sizeof))[0 .. sl]; 
    310             } 
    311             putstr(fbuf[0 .. sl]); 
    312         } 
    313         else 
    314         { 
    315             int sl; 
    316             char[] fbuf = tmpbuf; 
    317             char[12] format; 
    318             format[0] = '%'; 
    319             int i = 1; 
    320             if (flags & FLdash) 
    321                 format[i++] = '-'; 
    322             if (flags & FLplus) 
    323                 format[i++] = '+'; 
    324             if (flags & FLspace) 
    325                 format[i++] = ' '; 
    326             if (flags & FLhash) 
    327                 format[i++] = '#'; 
    328             if (flags & FL0pad) 
    329                 format[i++] = '0'; 
    330             format[i + 0] = '*'; 
    331             format[i + 1] = '.'; 
    332             format[i + 2] = '*'; 
    333             i += 3; 
    334             version (GNU_MinGW_MSVCRT) 
    335                 { /* nothing: no support for long double */ } 
    336             else 
    337                 static if (real.sizeof > double.sizeof) 
    338                 format[i++] = 'L'; 
    339             format[i++] = fc; 
    340             format[i] = 0; 
    341             if (!(flags & FLprecision)) 
    342                 precision = -1; 
    343             while (1) 
    344             {   int n; 
    345      
    346                 sl = fbuf.length; 
    347                 version (GNU_MinGW_MSVCRT) 
    348                 n = snprintf(fbuf.ptr, sl, format.ptr, field_width, precision, cast(double) v); 
    349                 else 
    350                 n = snprintf(fbuf.ptr, sl, format.ptr, field_width, precision, v); 
    351                 //printf("format = '%s', n = %d\n", cast(char*)format, n); 
    352                 if (n >= 0 && n < sl) 
    353                 {   sl = n; 
    354                 break; 
    355                 } 
    356                 if (n < 0) 
    357                 sl = sl * 2; 
    358                 else 
    359                 sl = n + 1; 
    360                 fbuf = (cast(char*)alloca(sl * char.sizeof))[0 .. sl]; 
    361             } 
    362             putstr(fbuf[0 .. sl]); 
    363         } 
    364         return; 
    365     } 
    366  
    367     static Mangle getMan(TypeInfo ti) 
    368     { 
    369         auto m = cast(Mangle)ti.classinfo.name[9]; 
    370         if (ti.classinfo.name.length == 20 && 
    371             ti.classinfo.name[9..20] == "StaticArray") 
    372         m = cast(Mangle)'G'; 
    373             return m; 
    374     } 
    375  
    376     void putArray(void* p, size_t len, TypeInfo valti) 
    377     { 
    378       putc('['); 
    379       size_t tsize = valti.tsize(); 
    380       version(DigitalMars) 
    381         auto argptrSave = argptr; 
    382       else 
    383           auto argptrSave = p_args; 
    384       auto tiSave = ti; 
    385       auto mSave = m; 
    386       ti = valti; 
    387       m = getMan(valti); 
    388       while (len--) 
    389       { 
    390         version (DigitalMars) 
    391             argptr = cast(void*) p; 
    392         else 
    393             p_args = p; 
    394         formatArg('s'); 
    395  
    396         p += tsize; 
    397         if (len > 0) putc(','); 
    398       } 
    399       m = mSave; 
    400       ti = tiSave; 
    401       version (DigitalMars) 
    402         argptr = argptrSave; 
    403       else 
    404         p_args = argptrSave; 
    405       putc(']'); 
    406     } 
    407  
    408     void putAArray(ubyte[long] vaa, TypeInfo valti, TypeInfo keyti) 
    409     { 
    410         // Copied from aaA.d 
    411         size_t aligntsize(size_t tsize) 
    412         { 
    413         // Is pointer alignment on the x64 4 bytes or 8? 
    414         return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1); 
    415         } 
    416          
    417       putc('['); 
    418       bool comma=false; 
    419       version (DigitalMars) 
    420         auto argptrSave = argptr; 
    421       else 
    422         auto argptrSave = p_args; 
    423       auto tiSave = ti; 
    424       auto mSave = m; 
    425       foreach(inout fakevalue; vaa) 
    426       { 
    427         if (comma) putc(','); 
    428         comma = true; 
    429         // the key comes before the value 
    430         ubyte* key = &fakevalue - long.sizeof; 
    431  
    432         version (DigitalMars) 
    433             argptr = cast(void*) key; 
    434         else 
    435             p_args = key; 
    436         ti = keyti; 
    437         m = getMan(keyti); 
    438         formatArg('s'); 
    439  
    440         putc(':'); 
    441         ubyte* value = key + aligntsize(keyti.tsize); 
    442         version (DigitalMars) 
    443             argptr = cast(void*) value; 
    444         else 
    445             p_args = value; 
    446         ti = valti; 
    447         m = getMan(valti); 
    448         formatArg('s'); 
    449       } 
    450       m = mSave; 
    451       ti = tiSave; 
    452       version (DigitalMars) 
    453         argptr = argptrSave; 
    454       else 
    455         p_args = argptrSave; 
    456       putc(']'); 
    457     } 
    458  
    459     if (! p_args) { 
    460     switch (m) 
    461     { 
    462         case Mangle.Tbool: 
    463         vbit = va_arg2!(bool)(argptr); 
    464         if (fc != 's') 
    465         {   vnumber = vbit; 
    466             goto Lnumber; 
    467         } 
    468         putstr(vbit ? "true" : "false"); 
    469         return; 
    470  
    471         case Mangle.Tchar: 
    472         vchar = va_arg2!(char)(argptr); 
    473         if (fc != 's') 
    474         {   vnumber = vchar; 
    475             goto Lnumber; 
    476         } 
    477         L2: 
    478         putstr((&vchar)[0 .. 1]); 
    479         return; 
    480  
    481         case Mangle.Twchar: 
    482         vdchar = va_arg2!(wchar)(argptr); 
    483         goto L1; 
    484  
    485         case Mangle.Tdchar: 
    486         vdchar = va_arg2!(dchar)(argptr); 
    487         L1: 
    488         if (fc != 's') 
    489         {   vnumber = vdchar; 
    490             goto Lnumber; 
    491         } 
    492         if (vdchar <= 0x7F) 
    493         {   vchar = cast(char)vdchar; 
    494             goto L2; 
    495         } 
    496         else 
    497         {   if (!isValid(vdchar)) 
    498             throw new Exception("invalid dchar in format"); 
    499             putstr(.toString([vdchar])); 
    500         } 
    501         return; 
    502  
    503         case Mangle.Tbyte: 
    504         signed = 1; 
    505         vnumber = va_arg2!(byte)(argptr); 
    506         goto Lnumber; 
    507  
    508         case Mangle.Tubyte: 
    509         vnumber = va_arg2!(ubyte)(argptr); 
    510         goto Lnumber; 
    511  
    512         case Mangle.Tshort: 
    513         signed = 1; 
    514         vnumber = va_arg2!(short)(argptr); 
    515         goto Lnumber; 
    516  
    517         case Mangle.Tushort: 
    518         vnumber = va_arg2!(ushort)(argptr); 
    519         goto Lnumber; 
    520  
    521         case Mangle.Tint: 
    522         signed = 1; 
    523         vnumber = va_arg2!(int)(argptr); 
    524         goto Lnumber; 
    525  
    526         case Mangle.Tuint: 
    527         Luint: 
    528         vnumber = va_arg2!(uint)(argptr); 
    529         goto Lnumber; 
    530  
    531         case Mangle.Tlong: 
    532         signed = 1; 
    533         vnumber = cast(ulong)va_arg2!(long)(argptr); 
    534         goto Lnumber; 
    535  
    536         case Mangle.Tulong: 
    537         Lulong: 
    538         vnumber = va_arg2!(ulong)(argptr); 
    539         goto Lnumber; 
    540  
    541         case Mangle.Tclass: 
    542         vobject = va_arg2!(Object)(argptr); 
    543         if (vobject is null) 
    544             s = "null"; 
    545         else 
    546             s = vobject.toString(); 
    547         goto Lputstr; 
    548  
    549         case Mangle.Tpointer: 
    550         vnumber = cast(size_t)va_arg2!(void*)(argptr); 
    551         uc = 1; 
    552         flags |= FL0pad; 
    553         if (!(flags & FLprecision)) 
    554         {   flags |= FLprecision; 
    555             precision = (void*).sizeof; 
    556         } 
    557         base = 16; 
    558         goto Lnumber; 
    559  
    560         case Mangle.Tfloat: 
    561         case Mangle.Tifloat: 
    562         if (fc == 'x' || fc == 'X') 
    563         { 
    564             version (DigitalMars) 
    565                 goto Luint; 
    566             else { 
    567                 float f = va_arg2!(float)(argptr); 
    568                 vnumber = *cast(uint*)&f; 
    569                 goto Lnumber; 
    570             } 
    571         } 
    572         vreal = va_arg2!(float)(argptr); 
    573         goto Lreal; 
    574  
    575         case Mangle.Tdouble: 
    576         case Mangle.Tidouble: 
    577         if (fc == 'x' || fc == 'X') 
    578         { 
    579             version (DigitalMars) 
    580                 goto Lulong; 
    581             else { 
    582                 double f = va_arg2!(double)(argptr); 
    583                 vnumber = *cast(ulong*)&f; 
    584                 goto Lnumber; 
    585             } 
    586         } 
    587         vreal = va_arg2!(double)(argptr); 
    588         goto Lreal; 
    589  
    590         case Mangle.Treal: 
    591         case Mangle.Tireal: 
    592         vreal = va_arg2!(real)(argptr); 
    593         goto Lreal; 
    594  
    595         case Mangle.Tcfloat: 
    596         vcreal = va_arg2!(cfloat)(argptr); 
    597         goto Lcomplex; 
    598  
    599         case Mangle.Tcdouble: 
    600         vcreal = va_arg2!(cdouble)(argptr); 
    601         goto Lcomplex; 
    602  
    603         case Mangle.Tcreal: 
    604         vcreal = va_arg2!(creal)(argptr); 
    605         goto Lcomplex; 
    606  
    607         case Mangle.Tsarray: 
    608         version (DigitalMars) { 
    609             putArray(argptr, (cast(TypeInfo_StaticArray)ti).len, (cast(TypeInfo_StaticArray)ti).next); 
    610             return; 
    611         } 
    612         version (GNU) { 
    613         /* Static arrays are converted to dynamic arrays when 
    614            passed as a variadic argument, so this code should 
    615            never be executed with GDC.  The case of an 
    616            embedded static array is handled below. */ 
    617            goto Lerror; 
    618         } 
    619  
    620         case Mangle.Tarray: 
    621         int mi = 10; 
    622         if (ti.classinfo.name.length == 14 && ti.classinfo.name[9..14] == "Array")  
    623         { // array of non-primitive types 
    624           TypeInfo tn = (cast(TypeInfo_Array)ti).next; 
    625           switch (cast(Mangle)tn.classinfo.name[9]) 
    626           { 
    627             case Mangle.Tchar:  goto LarrayChar; 
    628             case Mangle.Twchar: goto LarrayWchar; 
    629             case Mangle.Tdchar: goto LarrayDchar; 
    630             default: 
    631             break; 
    632           } 
    633           void[] va = va_arg2!(void[])(argptr); 
    634           putArray(va.ptr, va.length, tn); 
    635           return; 
    636         } 
    637         if (ti.classinfo.name.length == 25 && 
    638             ti.classinfo.name[9..25] == "AssociativeArray")  
    639         { // associative array 
    640           ubyte[long] vaa = va_arg2!(ubyte[long])(argptr); 
    641           putAArray(vaa, 
    642             (cast(TypeInfo_AssociativeArray)ti).next, 
    643             (cast(TypeInfo_AssociativeArray)ti).key); 
    644           return; 
    645         } 
    646  
    647         while (1) 
    648         { 
    649             m2 = cast(Mangle)ti.classinfo.name[mi]; 
    650             switch (m2) 
    651             { 
    652             case Mangle.Tchar: 
    653             LarrayChar: 
    654                 s = va_arg2!(char[])(argptr); 
    655                 goto Lputstr; 
    656  
    657             case Mangle.Twchar: 
    658             LarrayWchar: 
    659                 wchar[] sw = va_arg2!(wchar[])(argptr); 
    660                 s = .toString(sw); 
    661                 goto Lputstr; 
    662  
    663             case Mangle.Tdchar: 
    664             LarrayDchar: 
    665                 dchar[] sd = va_arg2!(dchar[])(argptr); 
    666                 s = .toString(sd); 
    667             Lputstr: 
    668                 if (fc != 's') 
    669                 throw new FormatError("string"); 
    670                 if (flags & FLprecision && precision < s.length) 
    671                 s = s[0 .. precision]; 
    672                 putstr(s); 
    673                 break; 
    674  
    675             case Mangle.Tconst: 
    676             case Mangle.Tinvariant: 
    677                 mi++; 
    678                 continue; 
    679  
    680             default: 
    681                 TypeInfo ti2 = primitiveTypeInfo(m2); 
    682                 if (!ti2) 
    683                     throw new FormatError("Can't get type info for type " ~ cast(char)m2); 
    684                 void[] va = va_arg2!(void[])(argptr); 
    685                 putArray(va.ptr, va.length, ti2); 
    686             } 
    687             return; 
    688         } 
    689         case Mangle.Ttypedef: 
    690         ti = (cast(TypeInfo_Typedef)ti).base; 
    691         m = cast(Mangle)ti.classinfo.name[9]; 
    692         formatArg(fc); 
    693         return; 
    694  
    695         case Mangle.Tenum: 
    696         ti = (cast(TypeInfo_Enum)ti).base; 
    697         m = cast(Mangle)ti.classinfo.name[9]; 
    698         formatArg(fc); 
    699         return; 
    700  
    701         case Mangle.Tstruct: 
    702         {   TypeInfo_Struct tis = cast(TypeInfo_Struct)ti; 
    703             if (tis.xtoString is null) 
    704                 throw new FormatError("Can't convert " ~ tis.toString() ~ " to string: \"string toString()\" not defined"); 
    705             version(DigitalMars){ 
    706                  
    707                 char[] delegate() toString; 
    708                 toString.ptr = argptr; 
    709                 toString.funcptr = cast(char[] function())tis.xtoString;  
    710                 s = Utf.fromString8 (toString(), s);                 
    711                 // s = tis.xtoString(argptr); 
    712                  
    713                 argptr += (tis.tsize() + 3) & ~3; 
    714             } 
    715             version (GNU){ 
    716             static if (is( typeof(argptr): void[] ) ||  is( typeof(argptr) == struct )) 
    717             { 
    718                 version(PPC) 
    719                 { 
    720                     // Structs are pass-by-reference in V4 ABI 
    721                     s = tis.xtoString(va_arg2!(void*)(argptr)); 
    722                 } 
    723                 else version(X86_64) 
    724                 { 
    725                     throw new FormatError("cannot portably format a struct on this target"); 
    726                 } 
    727                 else 
    728                 { 
    729                     static assert(0, "unimplemented"); 
    730                 } 
    731             } 
    732             else 
    733             { 
    734                 s = tis.xtoString(argptr); 
    735                 argptr += (tis.tsize() + 3) & ~3; // this looks like it should call aligntsize 
    736             } 
    737         } 
    738         goto Lputstr; 
    739         } 
    740  
    741         default: 
    742             if (m2=='v') 
    743                 throw new FormatError("Can't get type info for type void"); 
    744             else 
    745                 throw new FormatError("Can't get type info for mangled type " ~ cast(char)m2); 
    746     }} 
    747     else 
    748     { 
    749         version (DigitalMars) assert(0); 
    750         switch (m) 
    751         { 
    752         case Mangle.Tbool: 
    753             vbit = *cast(bool*)(p_args); p_args += bool.sizeof; // int.sizeof, etc.? 
    754             if (fc != 's') 
    755             {   vnumber = vbit; 
    756             goto Lnumber; 
    757             } 
    758             putstr(vbit ? "true" : "false"); 
    759             return; 
    760      
    761      
    762         case Mangle.Tchar: 
    763             vchar = *cast(char*)(p_args); p_args += char.sizeof; 
    764             if (fc != 's') 
    765             {   vnumber = vchar; 
    766             goto Lnumber; 
    767             } 
    768         PL2: // there is goto L2 outside of thise switch; it's okay to do that 
    769             putstr((&vchar)[0 .. 1]); 
    770             return; 
    771      
    772         case Mangle.Twchar: 
    773             vdchar = *cast(wchar*)(p_args); p_args += wchar.sizeof; 
    774             goto PL1; 
    775      
    776         case Mangle.Tdchar: 
    777             vdchar = *cast(dchar*)(p_args); p_args += dchar.sizeof; 
    778         PL1: 
    779             if (fc != 's') 
    780             {   vnumber = vdchar; 
    781                 goto Lnumber; 
    782             } 
    783             if (vdchar <= 0x7F) 
    784             {   vchar = cast(char)vdchar; 
    785                 goto PL2; 
    786             } 
    787             else 
    788             {   if (!isValid(vdchar)) 
    789                 throw new Exception("invalid dchar in format"); 
    790                 putstr(.toString([vdchar])); 
    791             } 
    792             return; 
    793      
    794      
    795         case Mangle.Tbyte: 
    796             signed = 1; 
    797             vnumber = *cast(byte*)p_args; p_args += byte.sizeof; 
    798             goto Lnumber; 
    799      
    800         case Mangle.Tubyte: 
    801             vnumber = *cast(ubyte*)p_args; p_args += ubyte.sizeof; 
    802             goto Lnumber; 
    803      
    804         case Mangle.Tshort: 
    805             signed = 1; 
    806             vnumber = *cast(short*)p_args; p_args += short.sizeof; 
    807             goto Lnumber; 
    808      
    809         case Mangle.Tushort: 
    810             vnumber = *cast(ushort*)p_args; p_args += ushort.sizeof; 
    811             goto Lnumber; 
    812      
    813         case Mangle.Tint: 
    814             signed = 1; 
    815             vnumber = *cast(int*)p_args; p_args += int.sizeof; 
    816             goto Lnumber; 
    817      
    818         case Mangle.Tuint: 
    819         PLuint: 
    820             vnumber = *cast(uint*)p_args; p_args += uint.sizeof; 
    821             goto Lnumber; 
    822      
    823         case Mangle.Tlong: 
    824             signed = 1; 
    825             vnumber = cast(ulong)*cast(long*)p_args; p_args += long.sizeof; 
    826             goto Lnumber; 
    827      
    828         case Mangle.Tulong: 
    829         PLulong: 
    830             vnumber = *cast(ulong*)p_args; p_args += ulong.sizeof; 
    831             goto Lnumber; 
    832      
    833         case Mangle.Tclass: 
    834             vobject = *cast(Object*)p_args; p_args += Object.sizeof; 
    835             s = vobject.toString(); 
    836             goto Lputstr; 
    837      
    838         case Mangle.Tpointer: 
    839             alias void * void_ponter_t; 
    840             vnumber = cast(size_t)*cast(void**)p_args; p_args += void_ponter_t.sizeof; 
    841             uc = 1; 
    842             flags |= FL0pad; 
    843             if (!(flags & FLprecision)) 
    844             {   flags |= FLprecision; 
    845                 precision = (void*).sizeof; 
    846             } 
    847             base = 16; 
    848             goto Lnumber; 
    849      
    850      
    851         case Mangle.Tfloat: 
    852         case Mangle.Tifloat: 
    853             if (fc == 'x' || fc == 'X') 
    854             goto PLuint; 
    855             vreal = *cast(float*)p_args; p_args += float.sizeof; 
    856             goto Lreal; 
    857      
    858         case Mangle.Tdouble: 
    859         case Mangle.Tidouble: 
    860             if (fc == 'x' || fc == 'X') 
    861             goto PLulong; 
    862             vreal = *cast(double*)p_args; p_args += double.sizeof; 
    863             goto Lreal; 
    864      
    865         case Mangle.Treal: 
    866         case Mangle.Tireal: 
    867             vreal = *cast(real*)p_args; p_args += real.sizeof; 
    868             goto Lreal; 
    869      
    870      
    871         case Mangle.Tcfloat: 
    872             vcreal = *cast(cfloat*)p_args; p_args += cfloat.sizeof; 
    873             goto Lcomplex; 
    874      
    875         case Mangle.Tcdouble: 
    876             vcreal = *cast(cdouble*)p_args; p_args += cdouble.sizeof; 
    877             goto Lcomplex; 
    878      
    879         case Mangle.Tcreal: 
    880             vcreal = *cast(creal*)p_args; p_args += creal.sizeof; 
    881             goto Lcomplex; 
    882      
    883         case Mangle.Tsarray: 
    884             putArray(p_args, (cast(TypeInfo_StaticArray)ti).len, (cast(TypeInfo_StaticArray)ti).next); 
    885             p_args += ti.tsize(); 
    886             return; 
    887  
    888         case Mangle.Tarray: 
    889             alias void[] array_t; 
    890             int mi = 10; 
    891             if (ti.classinfo.name.length == 14 && 
    892             ti.classinfo.name[9..14] == "Array")  
    893             { // array of non-primitive types 
    894               TypeInfo tn = (cast(TypeInfo_Array)ti).next; 
    895               switch (cast(Mangle)tn.classinfo.name[9]) 
    896               { 
    897             case Mangle.Tchar:  goto LarrayChar_p; 
    898             case Mangle.Twchar: goto LarrayWchar_p; 
    899             case Mangle.Tdchar: goto LarrayDchar_p; 
    900             default: 
    901                 break; 
    902               } 
    903               void[] va = *cast(void[]*)p_args; p_args += array_t.sizeof; 
    904               putArray(va.ptr, va.length, tn); 
    905               return; 
    906             } 
    907             if (ti.classinfo.name.length == 25 && 
    908             ti.classinfo.name[9..25] == "AssociativeArray")  
    909             { // associative array 
    910               ubyte[long] vaa = *cast(ubyte[long]*)p_args; p_args += vaa.sizeof; 
    911               putAArray(vaa, 
    912                 (cast(TypeInfo_AssociativeArray)ti).next, 
    913                 (cast(TypeInfo_AssociativeArray)ti).key); 
    914               return; 
    915             } 
    916  
    917             while (1) 
    918             { 
    919             m2 = cast(Mangle)ti.classinfo.name[mi]; 
    920             switch (m2) 
    921             { 
    922                 case Mangle.Tchar: 
    923                 LarrayChar_p: 
    924                 s = *cast(char[]*)p_args; p_args += array_t.sizeof; 
    925                 goto PLputstr; 
    926  
    927                 case Mangle.Twchar: 
    928                 LarrayWchar_p: 
    929                 wchar[] sw = *cast(wchar[]*)p_args; p_args += array_t.sizeof; 
    930                 s = .toString(sw); 
    931                 goto PLputstr; 
    932  
    933                 case Mangle.Tdchar: 
    934                 LarrayDchar_p: 
    935                 dchar[] sd = *cast(dchar[]*)p_args; p_args += array_t.sizeof; 
    936                 s = .toString(sd); 
    937                 PLputstr: 
    938                 if (fc != 's') 
    939                     throw new FormatError("string"); 
    940                 if (flags & FLprecision && precision < s.length) 
    941                     s = s[0 .. precision]; 
    942                 putstr(s); 
    943                 break; 
    944  
    945                 case Mangle.Tconst: 
    946                 case Mangle.Tinvariant: 
    947                 mi++; 
    948                 continue; 
    949  
    950                 default: 
    951                 TypeInfo ti2 = primitiveTypeInfo(m2); 
    952                 if (!ti2) 
    953                     throw new FormatError("Can't get type info for type " ~ cast(char)m2); 
    954                 void[] va = *cast(void[]*)p_args; p_args += array_t.sizeof; 
    955                 putArray(va.ptr, va.length, ti2); 
    956             } 
    957             return; 
    958             } 
    959      
    960         case Mangle.Ttypedef: 
    961             ti = (cast(TypeInfo_Typedef)ti).base; 
    962             m = cast(Mangle)ti.classinfo.name[9]; 
    963             formatArg(fc); 
    964             return; 
    965      
    966         case Mangle.Tenum: 
    967             ti = (cast(TypeInfo_Enum)ti).base; 
    968             m = cast(Mangle)ti.classinfo.name[9]; 
    969             formatArg(fc); 
    970             return; 
    971              
    972         case Mangle.Tstruct: 
    973         {   TypeInfo_Struct tis = cast(TypeInfo_Struct)ti; 
    974             if (tis.xtoString is null) 
    975             throw new FormatError("Can't convert " ~ tis.toString() ~ " to string: \"string toString()\" not defined"); 
    976              
    977              
    978             char[] delegate() toString; 
    979             toString.ptr = argptr; 
    980             toString.funcptr = cast(char[] function())tis.xtoString;  
    981             s = Utf.fromString8 (toString(), s); 
    982             // s = tis.xtoString(p_args); 
    983              
    984              
    985              
    986             p_args += tis.tsize(); 
    987             goto Lputstr; 
    988         } 
    989  
    990         default: 
    991             throw new FormatError("Could not format mangled type " ~ cast(char)m); 
    992         } 
    993     } 
    994  
    995     Lnumber: 
    996         switch (fc) 
    997         { 
    998             case 's': 
    999             case 'd': 
    1000             if (signed) 
    1001             {   if (cast(long)vnumber < 0) 
    1002                 {   prefix = "-"; 
    1003                 vnumber = -vnumber; 
    1004                 } 
    1005                 else if (flags & FLplus) 
    1006                 prefix = "+"; 
    1007                 else if (flags & FLspace) 
    1008                 prefix = " "; 
    1009             } 
    1010             break; 
    1011      
    1012             case 'b': 
    1013             signed = 0; 
    1014             base = 2; 
    1015             break; 
    1016      
    1017             case 'o': 
    1018             signed = 0; 
    1019             base = 8; 
    1020             break; 
    1021      
    1022             case 'X': 
    1023             uc = 1; 
    1024             if (flags & FLhash && vnumber) 
    1025                 prefix = "0X"; 
    1026             signed = 0; 
    1027             base = 16; 
    1028             break; 
    1029      
    1030             case 'x': 
    1031             if (flags & FLhash && vnumber) 
    1032                 prefix = "0x"; 
    1033             signed = 0; 
    1034             base = 16; 
    1035             break; 
    1036      
    1037             default: 
    1038                 throw new FormatError("Could not format number of mangled type " ~ fc); 
    1039         } 
    1040      
    1041         if (!signed) 
    1042         { 
    1043             switch (m) 
    1044             { 
    1045             case Mangle.Tbyte: 
    1046                 vnumber &= 0xFF; 
    1047                 break; 
    1048      
    1049             case Mangle.Tshort: 
    1050                 vnumber &= 0xFFFF; 
    1051                 break; 
    1052      
    1053             case Mangle.Tint: 
    1054                 vnumber &= 0xFFFFFFFF; 
    1055                 break; 
    1056      
    1057             default: 
    1058                 break; 
    1059             } 
    1060         } 
    1061      
    1062         if (flags & FLprecision && fc != 'p') 
    1063             flags &= ~FL0pad; 
    1064      
    1065         if (vnumber < base) 
    1066         { 
    1067             if (vnumber == 0 && precision == 0 && flags & FLprecision && 
    1068             !(fc == 'o' && flags & FLhash)) 
    1069             { 
    1070             putstr(null); 
    1071             return; 
    1072             } 
    1073             if (precision == 0 || !(flags & FLprecision)) 
    1074             {   vchar = cast(char)('0' + vnumber); 
    1075             if (vnumber < 10) 
    1076                 vchar = cast(char)('0' + vnumber); 
    1077             else 
    1078                 vchar = cast(char)((uc ? 'A' - 10 : 'a' - 10) + vnumber); 
    1079             goto L2; 
    1080             } 
    1081         } 
    1082      
    1083         int n = tmpbuf.length; 
    1084         char c; 
    1085         int hexoffset = uc ? ('A' - ('9' + 1)) : ('a' - ('9' + 1)); 
    1086      
    1087         while (vnumber) 
    1088         { 
    1089             c = cast(char)((vnumber % base) + '0'); 
    1090             if (c > '9') 
    1091             c += hexoffset; 
    1092             vnumber /= base; 
    1093             tmpbuf[--n] = c; 
    1094         } 
    1095         if (tmpbuf.length - n < precision && precision < tmpbuf.length) 
    1096         { 
    1097             int m = tmpbuf.length - precision; 
    1098             tmpbuf[m .. n] = '0'; 
    1099             n = m; 
    1100         } 
    1101         else if (flags & FLhash && fc == 'o') 
    1102             prefix = "0"; 
    1103         putstr(tmpbuf[n .. tmpbuf.length]); 
    1104         return; 
    1105  
    1106     Lreal: 
    1107         putreal(vreal); 
    1108         return; 
    1109  
    1110     Lcomplex: 
    1111         putreal(vcreal.re); 
    1112         putc('+'); 
    1113         putreal(vcreal.im); 
    1114         putc('i'); 
    1115         return; 
    1116  
    1117     Lerror: 
    1118         throw new FormatError("formatArg"); 
    1119     } 
    1120  
    1121     for (j = 0; j < arguments.length; ) 
    1122     {   ti = arguments[j++]; 
     1107    for (j = 0; j < arguments.length; ) 
     1108    {   ti = arguments[j++]; 
    11231109 
    11241110        flags = 0; 
     
    11291115        do 
    11301116        { 
    1131             if (ti.classinfo.name.length <= mi) 
    1132               throw new FormatError("Error parsing classinfo name: " ~ ti.classinfo.name); 
    1133             m = cast(Mangle)ti.classinfo.name[mi++]; 
     1117           if (ti.classinfo.name.length <= mi) 
     1118              throw new FormatError("Error parsing classinfo name: " ~ ti.classinfo.name); 
     1119           m = cast(Mangle)ti.classinfo.name[mi++]; 
    11341120        } while (m == Mangle.Tconst || m == Mangle.Tinvariant); 
    11351121     
    11361122        if (m == Mangle.Tarray) 
    11371123        { 
    1138             if (ti.classinfo.name.length == 14 && 
     1124           if (ti.classinfo.name.length == 14 && 
    11391125            ti.classinfo.name[9..14] == "Array")  
    1140            
    1141               TypeInfo tn = (cast(TypeInfo_Array)ti).next; 
    1142               switch (cast(Mangle)tn.classinfo.name[9]) 
    1143               { 
     1126           
     1127             TypeInfo tn = (cast(TypeInfo_Array)ti).next; 
     1128             switch (cast(Mangle)tn.classinfo.name[9]) 
     1129             { 
    11441130            case Mangle.Tchar: 
    11451131            case Mangle.Twchar: 
    11461132            case Mangle.Tdchar: 
    1147                 ti = tn; 
    1148                 mi = 9; 
    1149                 break; 
     1133               ti = tn; 
     1134               mi = 9; 
     1135               break; 
    11501136            default: 
    1151                 break; 
    1152               } 
    1153            
     1137               break; 
     1138             } 
     1139           
    11541140        L1: 
    1155             Mangle m2 = cast(Mangle)ti.classinfo.name[mi]; 
    1156             string  fmt;          // format string 
    1157             wstring wfmt; 
    1158             dstring dfmt; 
    1159      
    1160             /* For performance reasons, this code takes advantage of the 
    1161             * fact that most format strings will be ASCII, and that the 
    1162             * format specifiers are always ASCII. This means we only need 
    1163             * to deal with UTF in a couple of isolated spots. 
    1164             */ 
    1165      
    1166             if (! p_args) 
    1167             switch (m2) 
    1168            
    1169             case Mangle.Tchar: 
    1170                 fmt = va_arg2!(char[])(argptr); 
    1171                 break; 
    1172      
    1173             case Mangle.Twchar: 
    1174                 wfmt = va_arg2!(wchar[])(argptr); 
    1175                 fmt = .toString(wfmt); 
    1176                 break; 
    1177      
    1178             case Mangle.Tdchar: 
    1179                 dfmt = va_arg2!(dchar[])(argptr); 
    1180                 fmt = .toString(dfmt); 
    1181                 break; 
    1182      
    1183             case Mangle.Tconst: 
    1184             case Mangle.Tinvariant: 
    1185                 mi++; 
    1186                 goto L1; 
    1187      
    1188             default: 
    1189                 formatArg('s'); 
    1190                 continue; 
    1191            
    1192             else 
    1193            
    1194               version (DigitalMars) assert(0); 
     1141           Mangle m2 = cast(Mangle)ti.classinfo.name[mi]; 
     1142           string  fmt;           // format string 
     1143           wstring wfmt; 
     1144           dstring dfmt; 
     1145     
     1146           /* For performance reasons, this code takes advantage of the 
     1147            * fact that most format strings will be ASCII, and that the 
     1148            * format specifiers are always ASCII. This means we only need 
     1149            * to deal with UTF in a couple of isolated spots. 
     1150            */ 
     1151     
     1152           if (! p_args) 
     1153           switch (m2) 
     1154           
     1155               case Mangle.Tchar: 
     1156                   fmt = va_arg!(char[])(argptr); 
     1157                   break; 
     1158        
     1159               case Mangle.Twchar: 
     1160                   wfmt = va_arg!(wchar[])(argptr); 
     1161                   fmt = .toString(wfmt); 
     1162                   break; 
     1163        
     1164               case Mangle.Tdchar: 
     1165                   dfmt = va_arg!(dchar[])(argptr); 
     1166                   fmt = .toString(dfmt); 
     1167                   break; 
     1168        
     1169               case Mangle.Tconst: 
     1170               case Mangle.Tinvariant: 
     1171                   mi++; 
     1172                   goto L1; 
     1173        
     1174               default: 
     1175                   formatArg('s'); 
     1176                   continue; 
     1177           
     1178           else 
     1179           
     1180              version (DigitalMars) assert(0); 
    11951181                alias void[] array_t; 
    11961182                switch (m2) 
    11971183                { 
    1198                     case Mangle.Tchar: 
     1184                   case Mangle.Tchar: 
    11991185                    fmt = *cast(char[]*)p_args; p_args += array_t.sizeof; 
    12001186                    break; 
    12011187         
    1202                     case Mangle.Twchar: 
     1188                   case Mangle.Twchar: 
    12031189                    wfmt = *cast(wchar[]*)p_args; p_args += array_t.sizeof; 
    12041190                    fmt = .toString(wfmt); 
    12051191                    break; 
    12061192         
    1207                     case Mangle.Tdchar: 
     1193                   case Mangle.Tdchar: 
    12081194                    dfmt = *cast(dchar[]*)p_args; p_args += array_t.sizeof; 
    12091195                    fmt = .toString(dfmt); 
    12101196                    break; 
    12111197         
    1212                     case Mangle.Tconst: 
    1213                     case Mangle.Tinvariant: 
     1198                   case Mangle.Tconst: 
     1199                   case Mangle.Tinvariant: 
    12141200                    mi++; 
    12151201                    goto L1; 
    12161202         
    1217                     default: 
     1203                   default: 
    12181204                    formatArg('s'); 
    12191205                    continue; 
    12201206                } 
    1221            
    1222      
    1223             for (size_t i = 0; i < fmt.length; ) 
    1224             { dchar c = fmt[i++]; 
     1207           
     1208     
     1209           for (size_t i = 0; i < fmt.length; ) 
     1210           {  dchar c = fmt[i++]; 
    12251211     
    12261212                dchar getFmtChar() 
    12271213                {   // Valid format specifier characters will never be UTF 
    1228                     if (i == fmt.length) 
    1229                     throw new FormatError("invalid specifier"); 
    1230                     return fmt[i++]; 
     1214                   if (i == fmt.length) 
     1215                       throw new FormatError("invalid specifier"); 
     1216                   return fmt[i++]; 
    12311217                } 
    12321218         
     
    12341220                {   int n; 
    12351221         
    1236                     while (1) 
    1237                    
    1238                     n = n * 10 + (c - '0'); 
    1239                     if (n < 0)    // overflow 
    1240                         throw new FormatError("int overflow"); 
    1241                     c = getFmtChar(); 
    1242                     if (c < '0' || c > '9') 
    1243                         break; 
    1244                    
    1245                     return n; 
     1222                   while (1) 
     1223                   
     1224                       n = n * 10 + (c - '0'); 
     1225                       if (n < 0) // overflow 
     1226                           throw new FormatError("int overflow"); 
     1227                       c = getFmtChar(); 
     1228                       if (c < '0' || c > '9') 
     1229                           break; 
     1230                   
     1231                   return n; 
    12461232                } 
    12471233         
    12481234                int getFmtStar() 
    12491235                {   Mangle m; 
    1250                     TypeInfo ti; 
    1251          
    1252                     if (j == arguments.length) 
    1253                       throw new FormatError("too few arguments"); 
    1254                     ti = arguments[j++]; 
    1255                     m = cast(Mangle)ti.classinfo.name[9]; 
    1256                     if (m != Mangle.Tint) 
    1257                       throw new FormatError("int argument expected"); 
    1258                     if (! p_args) 
    1259                        return va_arg2!(int)(argptr); 
    1260                     else 
    1261                    
    1262                        version (DigitalMars) assert(0); 
    1263                     int result = *cast(int*)(p_args); p_args += int.sizeof; 
    1264                     return result; 
    1265                    
     1236                   TypeInfo ti; 
     1237         
     1238                   if (j == arguments.length) 
     1239                      throw new FormatError("too few arguments"); 
     1240                   ti = arguments[j++]; 
     1241                   m = cast(Mangle)ti.classinfo.name[9]; 
     1242                   if (m != Mangle.Tint) 
     1243                      throw new FormatError("int argument expected"); 
     1244                   if (! p_args) 
     1245                       return va_arg!(int)(argptr); 
     1246                   else 
     1247                   
     1248                       version (DigitalMars) assert(0); 
     1249                       int result = *cast(int*)(p_args); p_args += int.sizeof; 
     1250                       return result; 
     1251                   
    12661252                } 
    12671253         
    12681254                if (c != '%') 
    12691255                {   if (c > 0x7F)   // if UTF sequence 
    1270                     { i--;        // back up and decode UTF sequence 
     1256                   {  i--;        // back up and decode UTF sequence 
    12711257                        try { 
    1272                           c = fromString8([fmt[i]], [c])[0]; 
     1258                          c = fromString8([fmt[i]], [c])[0]; 
    12731259                        } catch (UnicodeException e) // invalid utf 
    12741260                        {    
    12751261                            i++; 
    12761262                        } 
    1277                    
     1263                   
    12781264                    Lputc: 
    1279                     putc(c); 
    1280                     continue; 
     1265                   putc(c); 
     1266                   continue; 
    12811267                } 
    12821268         
     
    12851271                while (1) 
    12861272                { 
    1287                     c = getFmtChar(); 
    1288                     switch (c) 
    1289                     { 
    1290                     case '-':   flags |= FLdash;    continue; 
    1291                     case '+':   flags |= FLplus;    continue; 
    1292                     case ' ':   flags |= FLspace;   continue; 
    1293                     case '#':   flags |= FLhash;    continue; 
    1294                     case '0':   flags |= FL0pad;    continue; 
    1295          
    1296                     case '%':   if (flags == 0) 
    1297                                 goto Lputc; 
    1298                     default:    break; 
    1299                     } 
    1300                     break; 
     1273                    c = getFmtChar(); 
     1274                    switch (c) 
     1275                    {   case '-':   flags |= FLdash;    continue; 
     1276                        case '+':   flags |= FLplus;    continue; 
     1277                        case ' ':   flags |= FLspace;   continue; 
     1278                        case '#':   flags |= FLhash;    continue; 
     1279                        case '0':   flags |= FL0pad;    continue; 
     1280             
     1281                        case '%':   if (flags == 0) 
     1282                                    goto Lputc; 
     1283                        default:    break; 
     1284                    } 
     1285                    break; 
    13011286                } 
    13021287         
     
    13051290                if (c == '*') 
    13061291                { 
    1307                     field_width = getFmtStar(); 
    1308                     if (field_width < 0) 
    1309                     {   flags |= FLdash; 
     1292                   field_width = getFmtStar(); 
     1293                   if (field_width < 0) 
     1294                   {   flags |= FLdash; 
    13101295                    field_width = -field_width; 
    1311                    
    1312          
    1313                     c = getFmtChar(); 
     1296                   
     1297         
     1298                   c = getFmtChar(); 
    13141299                } 
    13151300                else if (c >= '0' && c <= '9') 
    1316                     field_width = getFmtInt(); 
     1301                   field_width = getFmtInt(); 
    13171302         
    13181303                if (flags & FLplus) 
    1319                     flags &= ~FLspace; 
     1304                   flags &= ~FLspace; 
    13201305                if (flags & FLdash) 
    1321                     flags &= ~FL0pad; 
     1306                   flags &= ~FL0pad; 
    13221307         
    13231308                // Get precision 
     
    13261311                {   flags |= FLprecision; 
    13271312         
    1328                     c = getFmtChar(); 
    1329                     if (c == '*') 
    1330                    
     1313                   c = getFmtChar(); 
     1314                   if (c == '*') 
     1315                   
    13311316                    precision = getFmtStar(); 
    13321317                    if (precision < 0) 
    13331318                    {   precision = 0; 
    1334                         flags &= ~FLprecision; 
     1319                       flags &= ~FLprecision; 
    13351320                    } 
    13361321         
    13371322                    c = getFmtChar(); 
    1338                    
    1339                     else if (c >= '0' && c <= '9') 
     1323                   
     1324                   else if (c >= '0' && c <= '9') 
    13401325                    precision = getFmtInt(); 
    13411326                } 
     
    13481333                do 
    13491334                { 
    1350                     m = cast(Mangle)ti.classinfo.name[mi++]; 
     1335                   m = cast(Mangle)ti.classinfo.name[mi++]; 
    13511336                } while (m == Mangle.Tconst || m == Mangle.Tinvariant); 
    13521337         
     
    13541339                    throw new FormatError("Formatting specifiers can't be UTF");    // format specifiers can't be UTF 
    13551340                formatArg(cast(char)c); 
    1356            
     1341           
    13571342        } 
    13581343        else 
    13591344        { 
    1360             formatArg('s'); 
     1345           formatArg('s'); 
    13611346        } 
    1362    
    1363     return; 
    1364  
    1365     Lerror: 
    1366     throw new FormatError(); 
     1347   
     1348   return; 
     1349 
     1350   Lerror: 
     1351   throw new FormatError(); 
    13671352} 
    13681353  
     
    13701355 
    13711356version (skyos) 
    1372     version = no_hexfloat; 
     1357   version = no_hexfloat; 
    13731358 
    13741359 
    13751360unittest 
    13761361{ 
    1377     int i; 
    1378     string s; 
    1379  
    1380     debug(format) printf("yage.core.format.format.unittest\n"); 
     1362   int i; 
     1363   string s; 
     1364 
     1365   debug(format) printf("yage.core.format.format.unittest\n"); 
    13811366  
    1382     s = swritef("hello world! %s %s ", true, 57, 1_000_000_000, 'x', " foo"); 
    1383     assert(s == "hello world! true 57 1000000000x foo"); 
    1384  
    1385     s = swritef(1.67, " %A ", -1.28, float.nan); 
    1386     /* The host C library is used to format floats. 
    1387     * C99 doesn't specify what the hex digit before the decimal point 
    1388     * is for %A. 
    1389     */ 
     1367   s = swritef("hello world! %s %s ", true, 57, 1_000_000_000, 'x', " foo"); 
     1368   assert(s == "hello world! true 57 1000000000x foo"); 
     1369 
     1370   s = swritef(1.67, " %A ", -1.28, float.nan); 
     1371   /* The host C library is used to format floats. 
     1372    * C99 doesn't specify what the hex digit before the decimal point 
     1373    * is for %A. 
     1374    */ 
    13901375    
    1391     version (no_hexfloat) 
     1376   version (no_hexfloat) 
    13921377    { /*nothing*/ } 
    1393     else 
    1394     assert(s == "1.67 -0XA.3D70A3D70A3D8P-3 nan" || 
    1395            s == "1.67 -0X1.47AE147AE147BP+0 nan"); 
    1396  
    1397     s = swritef("%x %X", 0x1234AF, 0xAFAFAFAF); 
    1398     assert(s == "1234af AFAFAFAF"); 
    1399  
    1400     s = swritef("%b %o", 0x1234AF, 0xAFAFAFAF); 
    1401     assert(s == "100100011010010101111 25753727657"); 
    1402  
    1403     s = swritef("%d %s", 0x1234AF, 0xAFAFAFAF); 
    1404     assert(s == "1193135 2947526575"); 
    1405  
    1406     s = swritef("%s", 1.2 + 3.4i); 
    1407     assert(s == "1.2+3.4i"); 
    1408  
    1409     s = swritef("%x %X", 1.32, 6.78f); 
    1410     assert(s == "3ff51eb851eb851f 40D8F5C3"); 
    1411  
    1412     s = swritef("%#06.*f",2,12.345); 
    1413     assert(s == "012.35"); 
    1414  
    1415     s = swritef("%#0*.*f",6,2,12.345); 
    1416     assert(s == "012.35"); 
    1417  
    1418     s = swritef("%7.4g:", 12.678); 
    1419     assert(s == "  12.68:"); 
    1420  
    1421     s = swritef("%7.4g:", 12.678L); 
    1422     assert(s == "  12.68:"); 
    1423  
    1424     s = swritef("%04f|%05d|%#05x|%#5x",-4.,-10,1,1); 
    1425     assert(s == "-4.000000|-0010|0x001|  0x1"); 
    1426  
    1427     i = -10; 
    1428     s = swritef("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i); 
    1429     assert(s == "-10|-10|-10|-10|-10.0000"); 
    1430  
    1431     i = -5; 
    1432     s = swritef("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i); 
    1433     assert(s == "-5| -5|-05|-5|-5.0000"); 
    1434  
    1435     i = 0; 
    1436     s = swritef("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i); 
    1437     assert(s == "0|  0|000|0|0.0000"); 
    1438  
    1439     i = 5; 
    1440     s = swritef("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i); 
    1441     assert(s == "5|  5|005|5|5.0000"); 
    1442  
    1443     i = 10; 
    1444     s = swritef("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i); 
    1445     assert(s == "10| 10|010|10|10.0000"); 
    1446  
    1447     s = swritef("%.0d", 0); 
    1448     assert(s == ""); 
    1449  
    1450     s = swritef("%.g", .34); 
    1451     assert(s == "0.3"); 
    1452  
    1453     s = swritef("%.0g", .34); 
    1454     assert(s == "0.3"); 
    1455  
    1456     s = swritef("%.2g", .34); 
    1457     assert(s == "0.34"); 
    1458  
    1459     s = swritef("%0.0008f", 1e-08); 
    1460     assert(s == "0.00000001"); 
    1461  
    1462     s = swritef("%0.0008f", 1e-05); 
    1463     assert(s == "0.00001000"); 
    1464  
    1465     s = "helloworld"; 
    1466     string r; 
    1467     r = swritef("%.2s", s[0..5]); 
    1468     assert(r == "he"); 
    1469     r = swritef("%.20s", s[0..5]); 
    1470     assert(r == "hello"); 
    1471     r = swritef("%8s", s[0..5]); 
    1472     assert(r == "   hello"); 
    1473  
    1474     byte[] arrbyte = new byte[4]; 
    1475     arrbyte[0] = 100; 
    1476     arrbyte[1] = -99; 
    1477     arrbyte[3] = 0; 
    1478     r = swritef(arrbyte); 
    1479     assert(r == "[100,-99,0,0]"); 
    1480  
    1481     ubyte[] arrubyte = new ubyte[4]; 
    1482     arrubyte[0] = 100; 
    1483     arrubyte[1] = 200; 
    1484     arrubyte[3] = 0; 
    1485     r = swritef(arrubyte); 
    1486     assert(r == "[100,200,0,0]"); 
    1487  
    1488     short[] arrshort = new short[4]; 
    1489     arrshort[0] = 100; 
    1490     arrshort[1] = -999; 
    1491     arrshort[3] = 0; 
    1492     r = swritef(arrshort); 
    1493     assert(r == "[100,-999,0,0]"); 
    1494     r = swritef("%s",arrshort); 
    1495     assert(r == "[100,-999,0,0]"); 
    1496  
    1497     ushort[] arrushort = new ushort[4]; 
    1498     arrushort[0] = 100; 
    1499     arrushort[1] = 20_000; 
    1500     arrushort[3] = 0; 
    1501     r = swritef(arrushort); 
    1502     assert(r == "[100,20000,0,0]"); 
    1503  
    1504     int[] arrint = new int[4]; 
    1505     arrint[0] = 100; 
    1506     arrint[1] = -999; 
    1507     arrint[3] = 0; 
    1508     r = swritef(arrint); 
    1509     assert(r == "[100,-999,0,0]"); 
    1510     r = swritef("%s",arrint); 
    1511     assert(r == "[100,-999,0,0]"); 
    1512  
    1513     long[] arrlong = new long[4]; 
    1514     arrlong[0] = 100; 
    1515     arrlong[1] = -999; 
    1516     arrlong[3] = 0; 
    1517     r = swritef(arrlong); 
    1518     assert(r == "[100,-999,0,0]"); 
    1519     r = swritef("%s",arrlong); 
    1520     assert(r == "[100,-999,0,0]"); 
    1521  
    1522     ulong[] arrulong = new ulong[4]; 
    1523     arrulong[0] = 100; 
    1524     arrulong[1] = 999; 
    1525     arrulong[3] = 0; 
    1526     r = swritef(arrulong); 
    1527     assert(r == "[100,999,0,0]"); 
    1528  
    1529     string[] arr2 = new string[4]; 
    1530     arr2[0] = "hello"; 
    1531     arr2[1] = "world"; 
    1532     arr2[3] = "foo"; 
    1533     r = swritef(arr2); 
    1534     assert(r == "[hello,world,,foo]"); 
    1535  
    1536     r = swritef("%.8d", 7); 
    1537     assert(r == "00000007"); 
    1538     r = swritef("%.8x", 10); 
    1539     assert(r == "0000000a"); 
    1540  
    1541     r = swritef("%-3d", 7); 
    1542     assert(r == "7  "); 
    1543  
    1544     r = swritef("%*d", -3, 7); 
    1545     assert(r == "7  "); 
    1546  
    1547     r = swritef("%.*d", -3, 7); 
    1548     assert(r == "7"); 
    1549  
    1550     typedef int myint; 
    1551     myint m = -7; 
    1552     r = swritef(m); 
    1553     assert(r == "-7"); 
    1554  
    1555     r = swritef("abc"c); 
    1556     assert(r == "abc"); 
    1557     r = swritef("def"w); 
    1558     assert(r == "def"); 
    1559     r = swritef("ghi"d); 
    1560     assert(r == "ghi"); 
    1561  
    1562     void* p = cast(void*)0xDEADBEEF; 
    1563     r = swritef(p); 
    1564     assert(r == "DEADBEEF"); 
    1565  
    1566     r = swritef("%#x", 0xabcd); 
    1567     assert(r == "0xabcd"); 
    1568     r = swritef("%#X", 0xABCD); 
    1569     assert(r == "0XABCD"); 
    1570  
    1571     r = swritef("%#o", 012345); 
    1572     assert(r == "012345"); 
    1573     r = swritef("%o", 9); 
    1574     assert(r == "11"); 
    1575  
    1576     r = swritef("%+d", 123); 
    1577     assert(r == "+123"); 
    1578     r = swritef("%+d", -123); 
    1579     assert(r == "-123"); 
    1580     r = swritef("% d", 123); 
    1581     assert(r == " 123"); 
    1582     r = swritef("% d", -123); 
    1583     assert(r == "-123"); 
    1584  
    1585     r = swritef("%%"); 
    1586     assert(r == "%"); 
    1587  
    1588     r = swritef("%d", true); 
    1589     assert(r == "1"); 
    1590     r = swritef("%d", false); 
    1591     assert(r == "0"); 
    1592  
    1593     r = swritef("%d", 'a'); 
    1594     assert(r == "97"); 
    1595     wchar wc = 'a'; 
    1596     r = swritef("%d", wc); 
    1597     assert(r == "97"); 
    1598     dchar dc = 'a'; 
    1599     r = swritef("%d", dc); 
    1600     assert(r == "97"); 
    1601  
    1602     byte b = byte.max; 
    1603     r = swritef("%x", b); 
    1604     assert(r == "7f"); 
    1605     r = swritef("%x", ++b); 
    1606     assert(r == "80"); 
    1607     r = swritef("%x", ++b); 
    1608     assert(r == "81"); 
    1609  
    1610     short sh = short.max; 
    1611     r = swritef("%x", sh); 
    1612     assert(r == "7fff"); 
    1613     r = swritef("%x", ++sh); 
    1614     assert(r == "8000"); 
    1615     r = swritef("%x", ++sh); 
    1616     assert(r == "8001"); 
    1617  
    1618     i = int.max; 
    1619     r = swritef("%x", i); 
    1620     assert(r == "7fffffff"); 
    1621     r = swritef("%x", ++i); 
    1622     assert(r == "80000000"); 
    1623     r = swritef("%x", ++i); 
    1624     assert(r == "80000001"); 
    1625  
    1626     r = swritef("%x", 10); 
    1627     assert(r == "a"); 
    1628     r = swritef("%X", 10); 
    1629     assert(r == "A"); 
    1630     r = swritef("%x", 15); 
    1631     assert(r == "f"); 
    1632     r = swritef("%X", 15); 
    1633     assert(r == "F"); 
    1634  
    1635     Object c = null; 
    1636     r = swritef(c); 
    1637     assert(r == "null"); 
    1638  
    1639     enum TestEnum 
    1640    
    1641         Value1, Value2 
    1642    
    1643     r = swritef("%s", TestEnum.Value2); 
    1644     assert(r == "1"); 
    1645  
    1646     char[5][int] aa = ([3:"hello", 4:"betty"]); 
    1647     r = swritef("%s", aa.values); 
    1648     assert(r == "[[h,e,l,l,o],[b,e,t,t,y]]"); 
    1649     r = swritef("%s", aa); 
    1650     assert(r == "[3:[h,e,l,l,o],4:[b,e,t,t,y]]"); 
    1651  
    1652     static const dchar[] ds = ['a','b']; 
    1653     for (int j = 0; j < ds.length; ++j) 
    1654    
     1378   else 
     1379       assert(s == "1.67 -0XA.3D70A3D70A3D8P-3 nan" || 
     1380              s == "1.67 -0X1.47AE147AE147BP+0 nan"); 
     1381 
     1382   s = swritef("%x %X", 0x1234AF, 0xAFAFAFAF); 
     1383   assert(s == "1234af AFAFAFAF"); 
     1384 
     1385   s = swritef("%b %o", 0x1234AF, 0xAFAFAFAF); 
     1386   assert(s == "100100011010010101111 25753727657"); 
     1387 
     1388   s = swritef("%d %s", 0x1234AF, 0xAFAFAFAF); 
     1389   assert(s == "1193135 2947526575"); 
     1390 
     1391   s = swritef("%s", 1.2 + 3.4i); 
     1392   assert(s == "1.2+3.4i"); 
     1393 
     1394   s = swritef("%x %X", 1.32, 6.78f); 
     1395   assert(s == "3ff51eb851eb851f 40D8F5C3"); 
     1396 
     1397   s = swritef("%#06.*f",2,12.345); 
     1398   assert(s == "012.35"); 
     1399 
     1400   s = swritef("%#0*.*f",6,2,12.345); 
     1401   assert(s == "012.35"); 
     1402 
     1403   s = swritef("%7.4g:", 12.678); 
     1404   assert(s == "  12.68:"); 
     1405 
     1406   s = swritef("%7.4g:", 12.678L); 
     1407   assert(s == "  12.68:"); 
     1408 
     1409   s = swritef("%04f|%05d|%#05x|%#5x",-4.,-10,1,1); 
     1410   assert(s == "-4.000000|-0010|0x001|  0x1"); 
     1411 
     1412   i = -10; 
     1413   s = swritef("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i); 
     1414   assert(s == "-10|-10|-10|-10|-10.0000"); 
     1415 
     1416   i = -5; 
     1417   s = swritef("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i); 
     1418   assert(s == "-5| -5|-05|-5|-5.0000"); 
     1419 
     1420   i = 0; 
     1421   s = swritef("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i); 
     1422   assert(s == "0|  0|000|0|0.0000"); 
     1423 
     1424   i = 5; 
     1425   s = swritef("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i); 
     1426   assert(s == "5|  5|005|5|5.0000"); 
     1427 
     1428   i = 10; 
     1429   s = swritef("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i); 
     1430   assert(s == "10| 10|010|10|10.0000"); 
     1431 
     1432   s = swritef("%.0d", 0); 
     1433   assert(s == ""); 
     1434 
     1435   s = swritef("%.g", .34); 
     1436   assert(s == "0.3"); 
     1437 
     1438   s = swritef("%.0g", .34); 
     1439   assert(s == "0.3"); 
     1440 
     1441   s = swritef("%.2g", .34); 
     1442   assert(s == "0.34"); 
     1443 
     1444   s = swritef("%0.0008f", 1e-08); 
     1445   assert(s == "0.00000001"); 
     1446 
     1447   s = swritef("%0.0008f", 1e-05); 
     1448   assert(s == "0.00001000"); 
     1449 
     1450   s = "helloworld"; 
     1451   string r; 
     1452   r = swritef("%.2s", s[0..5]); 
     1453   assert(r == "he"); 
     1454   r = swritef("%.20s", s[0..5]); 
     1455   assert(r == "hello"); 
     1456   r = swritef("%8s", s[0..5]); 
     1457   assert(r == "   hello"); 
     1458 
     1459   byte[] arrbyte = new byte[4]; 
     1460   arrbyte[0] = 100; 
     1461   arrbyte[1] = -99; 
     1462   arrbyte[3] = 0; 
     1463   r = swritef(arrbyte); 
     1464   assert(r == "[100,-99,0,0]"); 
     1465 
     1466   ubyte[] arrubyte = new ubyte[4]; 
     1467   arrubyte[0] = 100; 
     1468   arrubyte[1] = 200; 
     1469   arrubyte[3] = 0; 
     1470   r = swritef(arrubyte); 
     1471   assert(r == "[100,200,0,0]"); 
     1472 
     1473   short[] arrshort = new short[4]; 
     1474   arrshort[0] = 100; 
     1475   arrshort[1] = -999; 
     1476   arrshort[3] = 0; 
     1477   r = swritef(arrshort); 
     1478   assert(r == "[100,-999,0,0]"); 
     1479   r = swritef("%s",arrshort); 
     1480   assert(r == "[100,-999,0,0]"); 
     1481 
     1482   ushort[] arrushort = new ushort[4]; 
     1483   arrushort[0] = 100; 
     1484   arrushort[1] = 20_000; 
     1485   arrushort[3] = 0; 
     1486   r = swritef(arrushort); 
     1487   assert(r == "[100,20000,0,0]"); 
     1488 
     1489   int[] arrint = new int[4]; 
     1490   arrint[0] = 100; 
     1491   arrint[1] = -999; 
     1492   arrint[3] = 0; 
     1493   r = swritef(arrint); 
     1494   assert(r == "[100,-999,0,0]"); 
     1495   r = swritef("%s",arrint); 
     1496   assert(r == "[100,-999,0,0]"); 
     1497 
     1498   long[] arrlong = new long[4]; 
     1499   arrlong[0] = 100; 
     1500   arrlong[1] = -999; 
     1501   arrlong[3] = 0; 
     1502   r = swritef(arrlong); 
     1503   assert(r == "[100,-999,0,0]"); 
     1504   r = swritef("%s",arrlong); 
     1505   assert(r == "[100,-999,0,0]"); 
     1506 
     1507   ulong[] arrulong = new ulong[4]; 
     1508   arrulong[0] = 100; 
     1509   arrulong[1] = 999; 
     1510   arrulong[3] = 0; 
     1511   r = swritef(arrulong); 
     1512   assert(r == "[100,999,0,0]"); 
     1513 
     1514   string[] arr2 = new string[4]; 
     1515   arr2[0] = "hello"; 
     1516   arr2[1] = "world"; 
     1517   arr2[3] = "foo"; 
     1518   r = swritef(arr2); 
     1519   assert(r == "[hello,world,,foo]"); 
     1520 
     1521   r = swritef("%.8d", 7); 
     1522   assert(r == "00000007"); 
     1523   r = swritef("%.8x", 10); 
     1524   assert(r == "0000000a"); 
     1525 
     1526   r = swritef("%-3d", 7); 
     1527   assert(r == "7  "); 
     1528 
     1529   r = swritef("%*d", -3, 7); 
     1530   assert(r == "7  "); 
     1531 
     1532   r = swritef("%.*d", -3, 7); 
     1533   assert(r == "7"); 
     1534 
     1535   typedef int myint; 
     1536   myint m = -7; 
     1537   r = swritef(m); 
     1538   assert(r == "-7"); 
     1539 
     1540   r = swritef("abc"c); 
     1541   assert(r == "abc"); 
     1542   r = swritef("def"w); 
     1543   assert(r == "def"); 
     1544   r = swritef("ghi"d); 
     1545   assert(r == "ghi"); 
     1546 
     1547   void* p = cast(void*)0xDEADBEEF; 
     1548   r = swritef(p); 
     1549   assert(r == "DEADBEEF"); 
     1550 
     1551   r = swritef("%#x", 0xabcd); 
     1552   assert(r == "0xabcd"); 
     1553   r = swritef("%#X", 0xABCD); 
     1554   assert(r == "0XABCD"); 
     1555 
     1556   r = swritef("%#o", 012345); 
     1557   assert(r == "012345"); 
     1558   r = swritef("%o", 9); 
     1559   assert(r == "11"); 
     1560 
     1561   r = swritef("%+d", 123); 
     1562   assert(r == "+123"); 
     1563   r = swritef("%+d", -123); 
     1564   assert(r == "-123"); 
     1565   r = swritef("% d", 123); 
     1566   assert(r == " 123"); 
     1567   r = swritef("% d", -123); 
     1568   assert(r == "-123"); 
     1569 
     1570   r = swritef("%%"); 
     1571   assert(r == "%"); 
     1572 
     1573   r = swritef("%d", true); 
     1574   assert(r == "1"); 
     1575   r = swritef("%d", false); 
     1576   assert(r == "0"); 
     1577 
     1578   r = swritef("%d", 'a'); 
     1579   assert(r == "97"); 
     1580   wchar wc = 'a'; 
     1581   r = swritef("%d", wc); 
     1582   assert(r == "97"); 
     1583   dchar dc = 'a'; 
     1584   r = swritef("%d", dc); 
     1585   assert(r == "97"); 
     1586 
     1587   byte b = byte.max; 
     1588   r = swritef("%x", b); 
     1589   assert(r == "7f"); 
     1590   r = swritef("%x", ++b); 
     1591   assert(r == "80"); 
     1592   r = swritef("%x", ++b); 
     1593   assert(r == "81"); 
     1594 
     1595   short sh = short.max; 
     1596   r = swritef("%x", sh); 
     1597   assert(r == "7fff"); 
     1598   r = swritef("%x", ++sh); 
     1599   assert(r == "8000"); 
     1600   r = swritef("%x", ++sh); 
     1601   assert(r == "8001"); 
     1602 
     1603   i = int.max; 
     1604   r = swritef("%x", i); 
     1605   assert(r == "7fffffff"); 
     1606   r = swritef("%x", ++i); 
     1607   assert(r == "80000000"); 
     1608   r = swritef("%x", ++i); 
     1609   assert(r == "80000001"); 
     1610 
     1611   r = swritef("%x", 10); 
     1612   assert(r == "a"); 
     1613   r = swritef("%X", 10); 
     1614   assert(r == "A"); 
     1615   r = swritef("%x", 15); 
     1616   assert(r == "f"); 
     1617   r = swritef("%X", 15); 
     1618   assert(r == "F"); 
     1619 
     1620   Object c = null; 
     1621   r = swritef(c); 
     1622   assert(r == "null"); 
     1623 
     1624   enum TestEnum 
     1625   
     1626       Value1, Value2 
     1627   
     1628   r = swritef("%s", TestEnum.Value2); 
     1629   assert(r == "1"); 
     1630 
     1631   char[5][int] aa = ([3:"hello", 4:"betty"]); 
     1632   r = swritef("%s", aa.values); 
     1633   assert(r == "[[h,e,l,l,o],[b,e,t,t,y]]"); 
     1634   r = swritef("%s", aa); 
     1635   assert(r == "[3:[h,e,l,l,o],4:[b,e,t,t,y]]"); 
     1636 
     1637   static const dchar[] ds = ['a','b']; 
     1638   for (int j = 0; j < ds.length; ++j) 
     1639   
    16551640    r = swritef(" %d", ds[j]); 
    16561641    if (j == 0) 
    1657         assert(r == " 97"); 
     1642       assert(r == " 97"); 
    16581643    else 
    1659         assert(r == " 98"); 
    1660    
    1661  
    1662     r = swritef(">%14d<, ", 15, [1,2,3]); 
    1663     assert(r == ">            15<, [1,2,3]"); 
     1644       assert(r == " 98"); 
     1645   
     1646 
     1647   r = swritef(">%14d<, ", 15, [1,2,3]); 
     1648   assert(r == ">            15<, [1,2,3]"); 
    16641649} 
  • trunk/src/yage/gui/style.d

    r186 r191  
    3030struct CSSValue 
    3131{    
     32    static const CSSValue AUTO;  /// Has a value of float.nan.  This means inherit from parent style. 
     33     
    3234    /** 
    3335     * CSSValues used to set units for measurements, such as width, padding, etc. */ 
     
    145147struct Style 
    146148{ 
    147  
    148149    /// CSSValues that can be assigned to the borderImagestyle property. 
    149150    enum BorderImageStyle 
    150     {   STRETCH, /// 
     151    {   STRETCH, /// Allowed values. 
    151152        ROUND, /// ditto 
    152153        REPEAT   /// ditto 
     
    155156    /// CSSValues that can be assigned to the fontStyle property. 
    156157    enum FontStyle 
    157     {   NORMAL, /// Allowed values. 
     158    {   AUTO, /// Allowed values. 
     159        NORMAL, /// ditto 
    158160        ITALIC /// ditto 
    159161    } 
     
    161163    /// CSSValues that can be assigned to the fontWeight property. 
    162164    enum FontWeight 
    163     {   NORMAL, /// Allowed values. 
     165    {   AUTO, /// Allowed values. 
     166        NORMAL, /// ditto 
    164167        BOLD /// ditto 
    165168    } 
     
    173176    /// CSSValues that can be assigned to the textAlign property. 
    174177    enum TextAlign 
    175     {   LEFT, /// Allowed values. 
     178    {   AUTO, /// Allowed values. 
     179        LEFT, /// ditto 
    176180        CENTER, /// ditto 
    177181        RIGHT, /// ditto 
     
    181185    /// CSSValues that can be assigned to the textDecoration property. 
    182186    enum TextDecoration 
    183     {   NONE, /// Allowed values. 
     187    {   AUTO, 
     188        NONE, /// Allowed values. 
    184189        UNDERLINE, /// ditto 
    185190        OVERLINE, /// ditto 
    186191        LINETHROUGH /// ditto 
    187192    } 
    188  
    189     /* 
    190     char[] enumToString(T)(T e) 
    191     { 
    192         return e.stringof; 
    193     }*/ 
    194193     
    195194    union {  
     
    267266 
    268267    // Cursor 
    269     Material cursor; 
    270     float cursorSize=float.nan; // in pixels, float.nan to default to size of image. 
     268    Material cursor; /// TODO 
     269    float cursorSize=float.nan; /// in pixels, float.nan to default to size of image. 
    271270     
    272271    /// Font properties 
    273272    Font fontFamily; 
    274     CSSValue fontSize = CSSValue(12); /// ditto 
     273    CSSValue fontSize; /// ditto 
    275274    FontStyle fontStyle; /// ditto 
    276275    FontWeight fontWeight; /// ditto 
    277276     
    278277    /// Text properties 
    279     Color color = {r:0, g:0, b:0, a:255}; 
     278    Color color = {r:0, g:0, b:0, a:255}; // TODO: How to have a value for AUTO? 
    280279    TextAlign textAlign = TextAlign.LEFT; /// ditto 
    281280    TextDecoration textDecoration = TextDecoration.NONE; /// ditto 
    282     CSSValue lineHeight = CSSValue(float.nan); /// ditto 
     281    CSSValue lineHeight; /// ditto 
    283282    CSSValue letterSpacing; /// ditto 
    284283     
    285284    /** 
    286285     * CSS 3D transform property, defaults to identity matrix.  See: http://w3.org/TR/css3-3d-transforms     */ 
    287     Matrix transform; 
    288     bool backfaceVisibility = true; 
     286    Matrix transform;    
    289287 
    290288    // Other 
     
    300298    bool visible = true; /// Set whether the element is visible. visibility is an alias of visible for CSS compatibility. 
    301299    int zIndex; /// Sets the stack order of the surface relative to its siblings. 
     300     
     301    bool backfaceVisibility = true; /// Draw the back side of surfaces if they're rotated in 3d. 
     302     
    302303 
    303304    /** 
     
    470471    }   } 
    471472    static char[] enumToString(Style.FontStyle style) /// ditto 
    472     {   return style==Style.FontStyle.NORMAL ? "normal" : "italic"; 
    473     } 
     473    {   switch(style) 
     474        {   case Style.FontStyle.AUTO: return "auto"; 
     475            case Style.FontStyle.NORMAL: return "normal"; 
     476            case Style.FontStyle.ITALIC: return "italic"; 
     477    }   } 
     478     
    474479    static char[] enumToString(Style.FontWeight style) /// ditto 
    475     {   return style==Style.FontWeight.NORMAL ? "normal" : "bold"; 
    476     } 
     480    {   switch(style) 
     481        {   case Style.FontWeight.AUTO: return "auto"; 
     482            case Style.FontWeight.NORMAL: return "normal"; 
     483            case Style.FontWeight.BOLD: return "bold"; 
     484    }   } 
    477485    static char[] enumToString(Style.Overflow style) /// ditto 
    478486    {   return style==Style.Overflow.VISIBLE ? "visible" : "hidden"; 
     
    480488    static char[] enumToString(Style.TextAlign style) /// ditto 
    481489    {   switch(style) 
    482         {   case Style.TextAlign.LEFT: return "left"; 
     490        {   case Style.TextAlign.AUTO: return "auto"; 
     491            case Style.TextAlign.LEFT: return "left"; 
    483492            case Style.TextAlign.CENTER: return "center"; 
    484493            case Style.TextAlign.RIGHT: return "right"; 
     
    487496    static char[] enumToString(Style.TextDecoration style) /// ditto 
    488497    {   switch(style) 
    489         {   case Style.TextDecoration.NONE: return "none"; 
     498        {   case Style.TextDecoration.AUTO: return "auto"; 
     499            case Style.TextDecoration.NONE: return "none"; 
    490500            case Style.TextDecoration.UNDERLINE: return "underline"; 
    491501            case Style.TextDecoration.OVERLINE: return "overline"; 
  • trunk/src/yage/gui/surface.d

    r186 r191  
    1717import yage.system.graphics.render; 
    1818import yage.system.window; 
     19import yage.resource.manager; 
    1920import yage.resource.texture; 
    2021import yage.resource.image; 
     
    3536     
    3637    char[] text; 
    37     bool editable = true;    
    38     bool mouseChildren = true; 
    39      
    40     TextLayout textLayout; 
    41      
    4238    protected char[] oldText; 
    4339    protected Texture textTexture;   
     40     
     41    bool editable = true; 
     42    bool mouseChildren = true; 
     43     
     44    TextLayout textLayout; 
    4445 
    4546    /// Callback functions 
    4647    bool delegate(Surface self) onBlur; /// 
    47     bool delegate(Surface self) onDraw; /// 
    4848    bool delegate(Surface self) onFocus; /// 
    4949    bool delegate(Surface self, byte buttons, Vec2i coordinates) onClick; /// unfinished 
     
    8484        ALT   = LALT | RALT, /// ditto 
    8585        META  = LMETA | RMETA /// ditto 
    86     }; 
    87      
    88     // internal values (TODO: these should be replaced with calculated style values) 
    89     Style calculatedStyle; 
     86    };   
    9087     
    9188    protected Vec2f offset;     // pixel distance of the topleft corner from parent's top left, a relative offset 
    9289    protected Vec2f size;       // pixel outer width/height, which includes borders and padding. 
    93     //public Vec4f border;      // now stored in calculatedStyle 
    94     //protected Vec4f padding;   
    9590     
    9691    public Vec2f offsetAbsolute;    // pixel distance of top left from the window's top left at 0, 0, an absolute offset 
    9792     
    9893    protected bool mouseIn;         // used to track mouseover/mouseout 
    99     protected bool _grabbed;   
     94    protected bool grabbed;    
    10095    protected bool resize_dirty = true; 
    10196     
    102     protected SurfaceGeometry geometry; 
    103      
    104     protected static final Style defaultStyle; 
    105      
    106     protected static Surface grabbedSurface; 
    107     protected static Surface focusSurface; 
    108  
    109     //
     97    protected SurfaceGeometry geometry; // geometry used to render this surface 
     98     
     99    protected static Style defaultStyle; // Used by getDefaultStyle()   
     100    protected static Surface grabbedSurface; // surface that has captured the mouse 
     101    protected static Surface focusSurface; // surface that has focus for receiving input 
     102 
     103    /** 
     104    * Create a new Surface at 0, 0 with 0 width and height. *
    110105    this() 
    111106    {   geometry = new SurfaceGeometry(); 
    112         updateDimensions(); 
     107        updateDimensions(getCalculatedStyle()); 
    113108        if (!focusSurface) 
    114109            focus(); 
     
    118113     * Release focus if this Surface has focus when it's destroyed. */ 
    119114    ~this() 
    120     {   if (focusSurface==this) 
     115    {   if (focusSurface is this) 
    121116            focusSurface = null; 
    122117    } 
     
    134129     * Get the inner-most width/height of the surface.  Just as with CSS, this is the width/height inside the padding. */ 
    135130    float width()  
    136     {   return innerWidth() - calculatedStyle.paddingLeft.value - calculatedStyle.paddingRight.value; 
     131    {   float parent_width = parentWidth(); 
     132        return innerWidth() - style.paddingLeft.toPx(parent_width, false) - style.paddingRight.toPx(parent_width, false); 
    137133    }    
    138134    float height() /// ditto 
    139     {   return innerHeight() - calculatedStyle.paddingTop.value - calculatedStyle.paddingBottom.value; 
     135    {   float parent_height = parentHeight(); 
     136        return innerHeight() - style.paddingTop.toPx(parent_height, false) - style.paddingBottom.toPx(parent_height, false); 
    140137    } 
    141138     
     
    143140     * Get the width/height of the surface, including the width/height of the padding, but not including the border. */ 
    144141    float innerWidth() 
    145     {   return outerWidth() - calculatedStyle.borderLeftWidth.value - calculatedStyle.borderRightWidth.value; 
     142    {   float parent_width = parentWidth(); 
     143        return outerWidth() - style.borderLeftWidth.toPx(parent_width, false) - style.borderRightWidth.toPx(parent_width, false); 
    146144    } 
    147145    float innerHeight() /// ditto 
    148     {   return outerHeight() - calculatedStyle.borderTopWidth.value - calculatedStyle.borderBottomWidth.value; 
     146    {   float parent_height = parentHeight(); 
     147        return outerHeight() - style.borderTopWidth.toPx(parent_height, false) - style.borderBottomWidth.toPx(parent_height, false); 
    149148    } 
    150149     
     
    187186        // Search self 
    188187        Vec2f[4] polygon; 
    189         getPolygon(polygon.ptr); 
     188        getPolygon(polygon); 
    190189        if (Vec2f(x, y).inside(polygon)) 
    191190            return this; 
    192191         
    193192        return null;         
    194     } 
    195      
    196      
    197     /** 
    198      * Get a style with all auto/null/inherit/% values replaced with absolute values. */ 
    199     Style getCalculatedStyle() 
    200     {   return calculatedStyle; 
    201     } 
    202      
     193    }    
    203194     
    204195    /** 
     
    250241    {    
    251242        // Get top, right, bottom, and left in terms of pixels, or nan. 
    252         Vec2f parent_size = Vec2f(parentWidth(), parentHeight()); 
     243        Vec2f parent_size = Vec2f(parentWidth(), parentHeight());       
    253244        Vec4f dimension; 
    254  
    255245        for (int i=0; i<4; i++) 
    256246        {   int xy = (i+1) % 2; 
     
    269259        { 
    270260            Vec2f[4] polygon; 
    271             getPolygon(polygon.ptr); 
     261            getPolygon(polygon); 
    272262 
    273263            for (int i=0; i<4; i++) 
     
    312302        } 
    313303         
    314         updateDimensions(); // dragging breaks w/o this. 
     304        updateDimensions(getCalculatedStyle()); // dragging breaks w/o this. 
    315305    } 
    316306     
     
    319309    void update() 
    320310    { 
    321         updateDimensions(); 
     311        Style cs = getCalculatedStyle(); 
     312        //alias calculatedStyle cs; 
     313        updateDimensions(cs); 
    322314        if (resize_dirty) 
    323315        {    
     
    325317            Vec4f padding; 
    326318            for (int i=0; i<4; i++) 
    327             {   border[i] = calculatedStyle.borderWidth[i].value; 
    328                 padding[i] = calculatedStyle.padding[i].value; 
     319            {   border[i] = cs.borderWidth[i].value; 
     320                padding[i] = cs.padding[i].value; 
    329321            } 
    330322            geometry.setDimensions(Vec2f(width(), height()), border, padding); 
    331          
    332          
    333323        } 
    334324         
     
    338328            int width = cast(int)width(); 
    339329            int height = cast(int)height(); 
    340             textLayout.update(text, style, width, height); 
    341             Image textImage = textLayout.render(style, true); // TODO: Change true to Probe.NextPow2 
     330             
     331            textLayout.update(text, cs, width, height);          
     332            Image textImage = textLayout.render(cs, true); // TODO: Change true to Probe.NextPow2 
    342333            assert(textImage !is null); 
    343334             
     
    345336                textTexture = new Texture(textImage, Texture.Format.AUTO, false, "Surface Text", true); 
    346337            else 
    347             //  textTexture.commit(textImage, false, false, text, true); 
    348338                textTexture.setImage(textImage); 
    349339            textTexture.padding = Vec2i(nextPow2(width)-width, -(nextPow2(height)-height)); 
     
    527517     * Params: 
    528518     *     polygon = A pointer to a Vec2f[4] where the result will be stored. */ 
    529     protected void getPolygon(Vec2f *polygon) 
    530     {   polygon[0] = Vec3f(0).transform(style.transform).vec2f + offset;            // top left 
     519    protected Vec2f[] getPolygon(in Vec2f[] polygon=null) 
     520    {   if (polygon.length < 4) 
     521            polygon = new Vec2f[4]; 
     522        polygon[0] = Vec3f(0).transform(style.transform).vec2f + offset;            // top left 
    531523        polygon[1] = Vec3f(size.x, 0, 0).transform(style.transform).vec2f + offset; // top right 
    532524        polygon[2] = size.vec3f.transform(style.transform).vec2f + offset;          // bottom right 
    533525        polygon[3] = Vec3f(0, size.y, 0).transform(style.transform).vec2f + offset; // bottom left 
     526        return polygon; 
    534527    } 
    535528     
     
    556549    // Get dimensions of this Surface's parent in pixels 
    557550    protected float parentWidth()  
    558     {   return parent ? parent.width() : Window.getInstance.getWidth();  
     551    {   return parent ? parent.width() : Window.getInstance().getWidth();  
    559552    } 
    560553    protected float parentHeight() // ditto 
    561554    {   return parent ? parent.height() : Window.getInstance.getHeight();  
     555    } 
     556     
     557 
     558    static Style getDefaultStyle() 
     559    { 
     560        if (!defaultStyle.fontFamily) 
     561        {   defaultStyle.fontFamily = ResourceManager.getDefaultFont(); 
     562            defaultStyle.fontSize = 12; 
     563            defaultStyle.fontStyle = Style.FontStyle.NORMAL; 
     564            defaultStyle.fontWeight = Style.FontWeight.NORMAL; 
     565            defaultStyle.color = "black"; 
     566            defaultStyle.textAlign = Style.TextAlign.LEFT; 
     567            defaultStyle.textDecoration = Style.TextDecoration.NONE;             
     568        } 
     569        return defaultStyle; 
     570    } 
     571     
     572    /** 
     573     * Get a style with all auto/null/inherit/% values replaced with absolute values. */ 
     574    Style getCalculatedStyle() 
     575    {    
     576        Style cs = style;  // calculated style 
     577        Style pcs = parent ? parent.getCalculatedStyle() : getDefaultStyle(); 
     578         
     579        // Font and text properties 
     580        cs.fontFamily = style.fontFamily is null ? pcs.fontFamily : style.fontFamily; 
     581        cs.fontSize = style.fontSize == CSSValue.AUTO ? pcs.fontSize : style.fontSize; 
     582        cs.fontStyle = style.fontStyle == Style.FontStyle.AUTO ? pcs.fontStyle : style.fontStyle; 
     583        cs.fontWeight = style.fontWeight == Style.FontWeight.AUTO ? pcs.fontWeight : style.fontWeight; 
     584        cs.textAlign = style.textAlign == Style.TextAlign.AUTO ? pcs.textAlign : style.textAlign; 
     585        cs.textDecoration = style.textDecoration == Style.TextDecoration.AUTO ? pcs.textDecoration : style.textDecoration; 
     586         
     587        // Dimensional properties: 
     588         
     589        // Convert all sizes to pixels 
     590        Vec2f parent_size = Vec2f(parentWidth(), parentHeight()); 
     591        cs.width = style.width.toPx(parent_size.x); 
     592        cs.height = style.height.toPx(parent_size.y);        
     593        for (int i=0; i<4; i++) 
     594        {   ubyte xy = i%2; 
     595            float scale_by = xy==0 ? parent_size.y : parent_size.x;          
     596            cs.padding[i] = style.padding[i].toPx(scale_by, false); 
     597            cs.borderWidth[i] = style.borderWidth[i].toPx(scale_by, false);          
     598            cs.dimension[i].value = style.dimension[i].toPx(parent_size[xy]); 
     599        } 
     600         
     601        // Ensure at least 4 of the 6 of top/right/bottom/left/width/height are set. 
     602        for (int xy=0; xy<2; xy++) 
     603        {   int topLeft= xy==0 ? 3 : 0; // top or left 
     604            int bottomRight = xy==0 ? 1 : 2; // bottom or right 
     605            if (isNaN(cs.dimension[topLeft].value)) 
     606            {   if (isNaN(cs.dimension[bottomRight].value)) 
     607                    cs.dimension[topLeft] = 0; 
     608                if (isNaN(cs.size[xy].value)) 
     609                    cs.size[xy] = parent_size[xy];           
     610            } 
     611        } 
     612        return cs; 
    562613    } 
    563614 
     
    565616     * Update the internally stored x, y, width, and height based on the style. 
    566617     * This will also update the geometry, recurse through children, and call the resize event if necessary. */ 
    567     protected void updateDimensions(
     618    protected void updateDimensions(Style cs
    568619    { 
    569620        Vec2f old_offset = offset; 
    570621        Vec2f old_size = size; 
    571          
    572         alias calculatedStyle cs; 
    573          
    574         // Copy/convert borders and padding to internal pixel values. 
     622                 
     623        // Convert style dimensions to pixels. 
    575624        Vec2f parent_size = Vec2f(parentWidth(), parentHeight()); 
    576         for (int i=0; i<4; i++) 
    577         {   float scale_by = i%2==0 ? parent_size.y : parent_size.x;             
    578             cs.padding[i] = style.padding[i].toPx(scale_by, false); 
    579             cs.borderWidth[i] = style.borderWidth[i].toPx(scale_by, false); 
    580         } 
    581          
    582         // Convert style dimensions to pixels.       
    583         Vec4f style_dimensions = Vec4f( 
    584             style.top.toPx(parent_size.y), 
    585             style.right.toPx(parent_size.x), 
    586             style.bottom.toPx(parent_size.y), 
    587             style.left.toPx(parent_size.x)); 
    588         Vec2f style_size = Vec2f( // style size doesn't include borders and padding, but the internal size does. 
    589             style.width.toPx(parent_size.x) + cs.borderLeftWidth.value + cs.borderRightWidth.value + cs.paddingLeft.value + cs.paddingRight.value,  
    590             style.height.toPx(parent_size.y) + cs.borderTopWidth.value + cs.borderBottomWidth.value + cs.paddingTop.value + cs.paddingBottom.value); 
    591          
    592         // This loop over xy combines the x/left/right and y/top/bottom calulations into one block of code. 
     625        Vec2f style_size = Vec2f( // style size doesn't include borders and padding, but this does. 
     626            cs.width.value + cs.borderLeftWidth.value + cs.borderRightWidth.value + cs.paddingLeft.value + cs.paddingRight.value,  
     627            cs.height.value + cs.borderTopWidth.value + cs.borderBottomWidth.value + cs.paddingTop.value + cs.paddingBottom.value); 
     628         
     629        // Calculate size and offset from top, left, bottom, right, width, height 
     630        // (at this point, at most only one of left/width/right will be NaN) 
    593631        for (int xy=0; xy<2; xy++) 
    594632        {   int topLeft= xy==0 ? 3 : 0; // top or left 
    595633            int bottomRight = xy==0 ? 1 : 2; // bottom or right 
     634 
     635            float grandparent_size=0, parent_border=0, parent_padding=0; 
     636            if (parent) 
     637            {   grandparent_size = xy==0 ? parent.parentHeight() : parent.parentWidth();             
     638                parent_border = parent.style.borderWidth[xy].toPx(grandparent_size, false); 
     639                parent_padding = parent.style.padding[xy].toPx(grandparent_size, false); 
     640            }                
    596641             
    597             // Ensure at least 4 of the 6 style dimensions are set. 
    598             if (isNaN(style_dimensions[topLeft])) 
    599             {   if (isNaN(style_dimensions[bottomRight])) 
    600                     style_dimensions[topLeft] = 0; 
    601                 if (isNaN(style_size[xy])) 
    602                     style_size[xy] = parent_size[xy];            
    603             } 
    604              
    605             float parent_border = (parent ? parent.calculatedStyle.borderWidth[xy].value : 0); 
    606             float parent_padding = (parent ? parent.calculatedStyle.padding[xy].value : 0); 
    607              
    608             // Position  
    609             // Convert CSS style top, left, bottom, right, width, height to internal pixel x, y, width, height. 
    610             // (at this point, at most only one of left/width/right will be NaN) 
    611             if (isNaN(style_dimensions[topLeft])) // top or left is NaN 
     642            if (isNaN(cs.dimension[topLeft].value)) // top or left is NaN 
    612643            {   size[xy] = style_size[xy]; 
    613                 offset[xy] = parent_size[xy] - size[xy] - style_dimensions[bottomRight] + parent_border + parent_padding; 
     644                offset[xy] = parent_size[xy] - size[xy] - cs.dimension[bottomRight].value + parent_border + parent_padding; 
    614645            } 
    615646            else if (isNaN(style_size[xy])) // width or height is NaN 
    616             {   offset[xy] = style_dimensions[topLeft]
    617                 size[xy] = (parent_size[xy] - style_dimensions[bottomRight]) - offset[xy]; 
     647            {   offset[xy] = cs.dimension[topLeft].value
     648                size[xy] = (parent_size[xy] - cs.dimension[bottomRight].value) - offset[xy]; 
    618649            } 
    619650            else // bottom or right is NaN 
    620             {   offset[xy] = style_dimensions[topLeft] + parent_border + parent_padding; 
     651            {   offset[xy] = cs.dimension[topLeft].value + parent_border + parent_padding; 
    621652                size[xy] = style_size[xy]; 
    622653        }   }    
     
    633664            resize(size-old_size); // trigger resize event. 
    634665            foreach (c; children) 
    635                 c.updateDimensions(); 
     666                c.updateDimensions(c.getCalculatedStyle()); 
    636667        } 
    637668    } 
  • trunk/src/yage/gui/textlayout.d

    r188 r191  
    368368{   // Font 
    369369    Font fontFamily; 
    370     int fontSize = 12; // default to 12px font size. 
     370    ushort fontSize = 12; // default to 12px font size. 
    371371    Color color = {r:0, g:0, b:0, a:255}; 
    372372    Style.FontWeight fontWeight; 
  • trunk/src/yage/resource/font.d

    r187 r191  
    185185        else 
    186186        {   Letter result; 
    187          
     187            
    188188            // Use regular or italic (shear) matrix? 
    189189            FT_Matrix matrix; 
  • trunk/src/yage/scene/camera.d

    r188 r191  
    203203    public void buildFrustum(Scene scene) 
    204204    {   //assert(!transform_dirty); 
    205         assert(System.isSystemThread()); // this shouldn't be necessary after removing the opengl calls. 
     205        //assert(System.isSystemThread()); // this shouldn't be necessary after removing the opengl calls. 
    206206         
    207207        // Create the clipping matrix from the modelview and projection matrices 
     
    229229        foreach (inout Plane p; frustum) 
    230230            p = p.normalize(); 
     231    } 
     232     
     233    override protected void calcTransform() 
     234    {   super.calcTransform(); 
     235        //if (scene) 
     236        //  buildFrustum(scene); 
    231237    } 
    232238