Changeset 102 for trunk

Show
Ignore:
Timestamp:
05/22/11 16:40:03 (1 year ago)
Author:
Chris Miller
Message:

Many updates

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/win32/entice/aboutform.d

    r101 r102  
    33 
    44 
    5 import dfl.all, dfl.winapi; 
     5import dfl.all, dfl.internal.winapi; 
    66 
    77import std.file, std.path; 
     
    215215        okBtn.name = "okBtn"; 
    216216        okBtn.text = "OK"; 
    217         okBtn.bounds = dfl.base.Rect(296, 240, 75, 23); 
     217        okBtn.bounds = dfl.all.Rect(296, 240, 75, 23); 
    218218        okBtn.parent = this; 
    219219        //~DFL Tabber:dfl.panel.Panel=tabs 
    220220        tabs = new Tabber(); 
    221221        tabs.name = "tabs"; 
    222         tabs.bounds = dfl.base.Rect(0, 0, 376, 232); 
     222        tabs.bounds = dfl.all.Rect(0, 0, 376, 232); 
    223223        tabs.parent = this; 
    224224        //~Entice Designer 0.8pre8 code ends here. 
  • trunk/win32/entice/advfindpanel.d

    r101 r102  
    66 
    77import std.path, std.thread, std.file, std.stream, 
    8     std.regexp, std.conv
     8    std.regexp, std.conv, std.string
    99 
    1010import dfl.scintilla, dfl.cpp.scintilla, dfl.cpp.scilexer; 
     
    321321        } 
    322322        return false; 
     323    } 
     324     
     325    static bool isFileOrDirHidden(char[] x) 
     326    { 
     327        bool wasdot = false; 
     328        foreach_reverse(char c; x) 
     329        { 
     330            if('.' == c) 
     331            { 
     332                wasdot = true; 
     333                continue; 
     334            } 
     335            if('\\' == c || '/' == c) 
     336            { 
     337                return wasdot; 
     338            } 
     339            wasdot = false; 
     340        } 
     341        return wasdot; 
    323342    } 
    324343     
     
    399418                            if(de.isdir()) 
    400419                            { 
     420                                if(isFileOrDirHidden(de.name)) 
     421                                    goto skip_this_dir; 
    401422                                foreach(char[] nodir; excludeDirs) 
    402423                                { 
     
    469490                                        if(de.isdir()) 
    470491                                        { 
     492                                            if(isFileOrDirHidden(de.name)) 
     493                                                goto skip_this_dir; 
    471494                                            foreach(char[] nodir; excludeDirs) 
    472495                                            { 
     
    621644 
    622645 
    623 class AdvFindScintilla: Scintilla 
     646class AdvFindScintilla: Scintilla, IFindReplaceTitle 
    624647{ 
    625648    static struct SCell 
     
    627650        char ch; // Character. 
    628651        ubyte st; // Style. 
     652    } 
     653     
     654     
     655    string findReplaceTitle() // getter 
     656    { 
     657        return "Find within Advanced Find results"; 
    629658    } 
    630659     
     
    715744        sendEditor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDERTAIL, SC_MARK_EMPTY); 
    716745         
    717         sendEditor(SCI_SETFOLDFLAGS, 16, 0); // 16  Draw line below if not expanded. 
     746        //sendEditor(SCI_SETFOLDFLAGS, 16, 0); // 16  Draw line below if not expanded. 
     747        //sendEditor(SCI_SETFOLDFLAGS, 2 | 4, 0); // 16  Draw line above (expanded & not) 
    718748         
    719749        sendEditor(SCI_SETMARGINSENSITIVEN, MARGIN_SCRIPT_FOLD_INDEX, 1); 
     
    881911    { 
    882912        sendEditor(SCI_SETSEL, -1, -1); // Set sel at very end, no selected chars, and scroll to it. The starting line should be in view. 
     913         
     914        //if(autoCollapseAdvancedFind) 
     915        { 
     916            int maxLine = sendEditor(SCI_GETLINECOUNT); 
     917            for(int iline = 0; iline < maxLine; iline++) 
     918            { 
     919                int level = sendEditor(SCI_GETFOLDLEVEL, iline); 
     920                if((level & SC_FOLDLEVELHEADERFLAG) 
     921                    && (SC_FOLDLEVELBASE == (level & SC_FOLDLEVELNUMBERMASK))) 
     922                { 
     923                    int lineMaxSubord = sendEditor(SCI_GETLASTCHILD, iline, -1); 
     924                    sendEditor(SCI_SETFOLDEXPANDED, iline, 0); 
     925                    if (lineMaxSubord > iline) 
     926                        sendEditor(SCI_HIDELINES, iline + 1, lineMaxSubord); 
     927                } 
     928            } 
     929        } 
     930         
    883931        startLine = sendEditor(SCI_LINEFROMPOSITION, int.max); // "The return value is the last line if pos is beyond the end of the document." 
    884932         
     
    891939            startLine++; 
    892940        } 
    893         s2 = "Searching for: "; 
     941        //s2 = "Searching for: "; 
     942        s2 = "Search for: "; 
    894943        s3 = searchingFor; 
    895944         
     
    10191068            afthd = null; 
    10201069             
    1021             //disp.forceAppend("Search stopped\r\n"); 
    10221070            disp.addEndLine(false); 
    10231071             
     
    10291077    this() 
    10301078    { 
     1079        flags |= ETabFlags.ALLOW_DETACH; 
    10311080        Entity ent = new Entity(); 
    10321081        super(ent, "Advanced Find"); 
     
    10491098                 
    10501099                findpanel.findBtn.enabled = true; 
     1100                findpanel.findBox.select(); 
    10511101            }); 
    10521102    } 
     
    10571107    { 
    10581108        char[1024 * 4] buf = void; 
    1059          
    10601109        disp.sendEditor(SCI_GETCURLINE, buf.length, cast(size_t)buf.ptr); 
     1110        string line = .toString(buf); 
    10611111        disp.selectionLength = 0; 
    1062          
    1063         size_t iw; 
    1064         size_t lparen = 0, rparen = 0, colon = 0; 
    1065         for(iw = 0; buf[iw]; iw++) 
    1066         { 
    1067             if('(' == buf[iw]) 
    1068             { 
    1069                 lparen = iw; 
    1070                 rparen = 0; 
    1071             } 
    1072             else if(')' == buf[iw]) 
    1073             { 
    1074                 if(lparen) 
    1075                     rparen = iw; 
    1076             } 
    1077             else if(':' == buf[iw] && iw > 1) 
    1078             { 
    1079                 char[] fn; 
    1080                 uint linnum; 
    1081                 if(lparen && rparen) 
    1082                 { 
    1083                     fn = buf[0 .. lparen]; 
    1084                     try 
    1085                     { 
    1086                         linnum = std.conv.toUint(buf[lparen + 1 .. rparen]); 
    1087                     } 
    1088                     catch 
    1089                     { 
    1090                     } 
    1091                 } 
    1092                 else if(colon) 
    1093                 { 
    1094                     fn = buf[0 .. colon]; 
    1095                 } 
    1096                 else 
    1097                 { 
    1098                     break; 
    1099                 } 
    1100                 fn = fn.dup; 
    1101                  
    1102                 auto altdown = Control.modifierKeys & Keys.ALT; 
    1103                  
    1104                 auto clpos = disp.sendEditor(SCI_POSITIONFROMLINE, -1); // Current line position. 
    1105                 disp.sendEditor(SCI_SETSEL, clpos, clpos + fn.length); 
    1106                  
    1107                 if(mainForm) 
    1108                 { 
    1109                     EditorTab etab; 
    1110                      
    1111                     mainForm.doOpen(fn, true); // wantEditor = true 
    1112                     etab = cast(EditorTab)getCurrentTab(); 
    1113                     if(!etab) 
    1114                         break; 
    1115                     //if(etab is this) 
    1116                     //  break; 
    1117                      
    1118                     if(linnum) 
    1119                     { 
    1120                         Application.doEvents(); 
    1121                         if(altdown) 
    1122                         { 
    1123                             //EditorTab etab = cast(EditorTab)getCurrentTab(); 
    1124                             //if(etab) 
    1125                             { 
    1126                                 etab.switchToOppositeView(); 
    1127                                 Application.doEvents(); // ! 
    1128                             } 
    1129                         } 
    1130                         mainForm.doGotoLine(etab.asci, linnum); 
    1131                         //Application.doEvents(); 
    1132                         //etab.asci.select(); 
    1133                         etab.asci.delayInvoke( 
    1134                             function(Control cc, size_t[] params) 
    1135                             { 
    1136                                 cc.select(); 
    1137                             }, null); 
    1138                     } 
    1139                 } 
    1140                  
    1141                 break; 
    1142             } 
    1143         } 
     1112        doubleclickedStatusOpenFile(line); 
    11441113    } 
    11451114     
     
    11501119        findpanel.invoke( 
    11511120            { 
    1152                 if(file.length
     1121                if(file.length && afthd
    11531122                { 
    11541123                    //disp.forceAppend(std.string.format("%s(%s): %s\r\n", file, linnum, matchline)); 
     
    12221191     
    12231192     
     1193    Form detachform; 
     1194     
     1195    Form getDetachForm(Tabber tabc, int index) 
     1196    { 
     1197        if(detachform) 
     1198            return detachform; 
     1199        detachform = new DetachedTabForm(tabc, tabc.tabs[index]); 
     1200        detachform.owner = mainForm; 
     1201        detachform.clientSize = Size(700, 500); 
     1202        return detachform; 
     1203    } 
     1204     
     1205     
     1206    override void onDetach(Tabber tabc, int index) 
     1207    { 
     1208        if(findpanel && disp) 
     1209        { 
     1210            if(!detachform) 
     1211                detachform = getDetachForm(tabc, index); 
     1212            { 
     1213                findpanel.parent = detachform; 
     1214                disp.parent = detachform; 
     1215                detachform.show(); 
     1216                findpanel.bringToFront(); 
     1217            } 
     1218        } 
     1219    } 
     1220     
     1221     
     1222    override void onAttach(Tabber tabc, int index) 
     1223    { 
     1224        if(detachform) 
     1225        { 
     1226            findpanel.parent = tabc; 
     1227            disp.parent = tabc; 
     1228            detachform.close(); 
     1229            detachform = null; 
     1230        } 
     1231        if(findpanel && disp) 
     1232        { 
     1233            findpanel.parent = tabc; 
     1234            disp.parent = tabc; 
     1235            findpanel.bringToFront(); 
     1236        } 
     1237    } 
     1238     
     1239     
    12241240    override void onHide(Tabber tabc, int index) 
    12251241    { 
     
    12341250    { 
    12351251        super.onShow(tabc, index); 
     1252         
     1253        Control tparent = tabc; 
     1254        if(tabc.tabs[index].detached) 
     1255        { 
     1256            if(!detachform) 
     1257                detachform = getDetachForm(tabc, index); 
     1258            tparent = detachform; 
     1259        } 
    12361260         
    12371261        if(!findpanel) 
     
    12441268                dock = DockStyle.TOP; 
    12451269                backColor = SystemColors.control; // Because of tabber's color. 
    1246                 parent = tabc
     1270                parent = tparent
    12471271                //show(); 
    12481272                //findBox.select(); // Need to select it each show because of hiding/showing the tab removes the selection. 
     
    12551279            { 
    12561280                dock = DockStyle.FILL; 
    1257                 parent = tabc
     1281                parent = tparent
    12581282                 
    12591283                doubleClick ~= &disp_doubleClick; 
     
    12631287        findpanel.show(); 
    12641288        //findpanel.findBox.select(); // Not needed anymore; handled in DFL. 
     1289        if(detachform) 
     1290            detachform.acceptButton = findpanel.findBtn; 
    12651291        mainForm.acceptButton = findpanel.findBtn; 
    12661292        disp.show(); 
     1293        tparent.show(); 
    12671294         
    12681295        DdFindReplace.sci = disp; // Let the user find within the advanced find results. 
     
    12901317        i = tabs.addTab(advfindtab); 
    12911318    } 
    1292     tabs.selectedIndex = i; 
     1319    if(!tabs.tabs[i].detached) 
     1320        tabs.selectedIndex = i; 
     1321     
     1322    advfindtab.findpanel.findBox.select(); 
    12931323} 
    12941324 
  • trunk/win32/entice/apiinfo.d

    r101 r102  
    88 
    99import util : nextWord; 
     10 
     11 
     12debug 
     13{ 
     14    version = API_PICKY_JSON; 
     15    version = addApiEntry_THROWS; 
     16} 
    1017 
    1118 
     
    557564    char[] name; // "std.file.read" would be "read". 
    558565    ApiFlags flags; 
     566    //ushort line; // Only set via JSON. 
    559567     
    560568     
     
    784792        return data.ptr[0 .. length]; 
    785793    } 
     794     
     795    const int MAX_LENGTH = ushort.max; 
    786796} 
    787797 
     
    12061216        pparent = findEntry(toparent); 
    12071217        if(!pparent) 
     1218        { 
     1219            version(addApiEntry_THROWS) 
     1220                throw new Exception(std.string.format("... Unable to add `%.*s . %.*s` - cannot find parent\n", toparent, ae.name)); 
    12081221            return; 
     1222        } 
    12091223         
    12101224        if(pparent.type & ApiType.NEST) 
     1225        { 
    12111226            (cast(ApiNest*)pparent).addNestEntry(ae); 
     1227        } 
     1228        else 
     1229        { 
     1230            version(addApiEntry_THROWS) 
     1231                throw new Exception(std.string.format("... Unable to add `%.*s . %.*s` - cannot nest in parent\n", toparent, ae.name)); 
     1232            return; 
     1233        } 
    12121234    } 
    12131235     
     
    12981320                break; 
    12991321            } 
     1322            /+remainbytes--; 
     1323            if(remainbytes < 0) 
     1324            { 
     1325                assert(remainbytes >= 0, "loadApiInfo, streamReadLine: reamainbytes is negative"); 
     1326                remainbytes = 0; 
     1327            }+/ 
    13001328            if('\r' == ch) 
    13011329            { 
     
    13221350    } 
    13231351     
    1324      
     1352    char _jtNext = 0; 
     1353    bool streamReadJsonToken() 
     1354    { 
     1355        if(_jtNext) 
     1356        { 
     1357            _linebuf[0] = _jtNext; 
     1358            _jtNext = 0; 
     1359            line = _linebuf[0 .. 1]; 
     1360            return true; 
     1361        } 
     1362        line = null; 
     1363        bool isgood = true; 
     1364        size_t srliw = 0; 
     1365        char ch; 
     1366        bool instring = false; 
     1367        bool inescape = false; 
     1368        charloop: 
     1369        for(;;) 
     1370        { 
     1371            if(srliw >= _linebuf.length) 
     1372                break; // ? or should it keep reading until the end of the line. 
     1373            if(1 != stm.readBlock(&ch, 1)) 
     1374            { 
     1375                isgood = false; 
     1376                break; 
     1377            } 
     1378            /+remainbytes--; 
     1379            if(remainbytes < 0) 
     1380            { 
     1381                assert(remainbytes >= 0, "loadApiInfo, streamReadJsonToken: reamainbytes is negative"); 
     1382                remainbytes = 0; 
     1383            }+/ 
     1384            if(instring) 
     1385            { 
     1386                if(inescape) 
     1387                { 
     1388                    inescape = false; 
     1389                } 
     1390                else 
     1391                { 
     1392                    if(ch == '"') 
     1393                    { 
     1394                        instring = false; 
     1395                    } 
     1396                    else if(ch == '\\') 
     1397                    { 
     1398                        inescape = true; 
     1399                    } 
     1400                } 
     1401                _linebuf[srliw++] = ch; 
     1402                if(!instring) 
     1403                { 
     1404                    break; 
     1405                } 
     1406            } 
     1407            else 
     1408            { 
     1409                switch(ch) 
     1410                { 
     1411                    case '\r': 
     1412                    case '\n': 
     1413                    case ' ': 
     1414                    case '\t': 
     1415                    case '\f': 
     1416                    case '\v': 
     1417                        if(srliw) 
     1418                            break charloop; 
     1419                        break; 
     1420                     
     1421                    case '[': 
     1422                    case ']': 
     1423                    case '{': 
     1424                    case '}': 
     1425                    case ':': 
     1426                    case ',': 
     1427                        if(srliw) 
     1428                        { 
     1429                            _jtNext = ch; 
     1430                            break charloop; 
     1431                        } 
     1432                        _linebuf[srliw++] = ch; 
     1433                        break charloop; 
     1434                     
     1435                    case '"': 
     1436                        instring = true; 
     1437                        _linebuf[srliw++] = ch; 
     1438                        break; 
     1439                     
     1440                    default: 
     1441                        _linebuf[srliw++] = ch; 
     1442                        break; 
     1443                } 
     1444            } 
     1445        } 
     1446        if(!srliw) 
     1447            return isgood; 
     1448        line = _linebuf[0 .. srliw]; 
     1449        if(instring) 
     1450        { 
     1451            version(API_PICKY_JSON) 
     1452                throw new Exception("Unterminated string in JSON: " ~ line); 
     1453            return false; 
     1454        } 
     1455        return true; 
     1456    } 
     1457     
     1458    char[] nextJsonToken() 
     1459    { 
     1460        if(!streamReadJsonToken()) 
     1461        { 
     1462            return null; 
     1463        } 
     1464        //printf(" `%.*s`", line); 
     1465        return line; 
     1466    } 
     1467     
     1468    ApiInfo api; 
     1469    api = new ApiInfo; 
     1470    api.name = name; 
     1471     
     1472    LoadingApi lapi; 
     1473    lapi.api = api; 
     1474     
     1475    bool isjson = false; 
     1476    while(streamReadLine()) 
     1477    { 
     1478        string s = std.string.strip(line); 
     1479        if(s.length == 0) 
     1480        { 
     1481            continue; 
     1482        } 
     1483        if("[" == s) 
     1484        { 
     1485            isjson = true; 
     1486        } 
     1487        else if('[' == s[0]) 
     1488        { 
     1489            throw new Exception("Expected [ on its own line in JSON file for " ~ api.name ~ " API plugin"); 
     1490        } 
     1491        else 
     1492        { 
     1493            isjson = false; 
     1494        } 
     1495        break; 
     1496    } 
     1497    if(isjson) 
     1498    { 
     1499        lapi._jsonLoadMembers(&nextJsonToken); 
     1500    } 
     1501    else 
     1502    { 
     1503        if(line.length) 
     1504            lapi._dapiLoadLine(line); 
     1505        while(streamReadLine()) 
     1506        { 
     1507            lapi._dapiLoadLine(line); 
     1508        } 
     1509    } 
     1510     
     1511    if(addGlobal) 
     1512        addGlobalApiInfo(api); 
     1513     
     1514    return api; 
     1515
     1516 
     1517 
     1518private struct LoadingApi 
     1519
    13251520    ApiInfo api; 
    13261521    void[] _mpool; // Current malloc memory pool. 
    1327     api = new ApiInfo; 
    1328     api.name = name; 
    1329      
     1522    //long remainbytes; 
     1523    uint curline; 
    13301524     
    13311525    // Allocates from the malloc memory pool. 
     
    13401534            if(n > MIN_POOL_SIZE) 
    13411535                mpn = round2power(n); 
    1342             // Determine how much extra to preallocate based on remaining bytes in stream. 
    13431536            size_t pren; 
    1344             pren = round2power((stm.size() - stm.position()) / 8); 
     1537            //pren = round2power(remainbytes / 8); 
     1538            pren = round2power(1024 * 4); 
    13451539            if(pren > MAX_POOL_SIZE) 
    13461540                pren = MAX_POOL_SIZE; 
     
    13591553    void errmodpath() 
    13601554    { 
    1361         throw new Exception("Module path too long"); 
    1362     } 
     1555        throw new Exception("Fully-qualified name too long for API information"); 
     1556    } 
     1557     
    13631558     
    13641559    char[2048] parentbuf; 
    1365     char[] curmodule; // Refers to first (curmodule.length) bytes of parentbuf, and parentbuf[curmodule.length] is '.'. 
    1366      
    1367     char[] s, s2; 
    1368     int i; 
    1369     while(streamReadLine()) 
    1370     { 
    1371         switch(nextWord(line)) 
    1372         { 
    1373             case "module": 
     1560    char[] curscope; // Refers to first (curscope.length) bytes of parentbuf, and parentbuf[curscope.length] is '.'. 
     1561    // Note: curscope is different for JSON and DAPI; for DAPI it's the module. 
     1562     
     1563     
     1564    // Already ate '['. 
     1565    void _jsonLoadMembers(char[] delegate() nexttok) 
     1566    { 
     1567        // Note: string returned by nexttok is temporary. 
     1568         
     1569        char[] prevmodule = curscope; 
     1570         
     1571        char[] decodeString(char[] str, char[] buf) 
     1572        { 
     1573            if(str.length < 1 || '"' != str[0]) 
     1574            { 
     1575                return buf[0 .. 0]; 
     1576            } 
     1577            bool inescape = false; 
     1578            int ibuf = 0; 
     1579            strloop: 
     1580            for(int i = 1; i < str.length; i++) 
     1581            { 
     1582                if(inescape) 
    13741583                { 
    1375                     s = nextWord(line); 
    1376                     if(s.length) 
    1377                     { 
    1378                         if(s.length >= parentbuf.length - 128) 
    1379                             errmodpath(); 
     1584                    switch(str[i]) 
     1585                    { 
     1586                        case 'r': 
     1587                            buf[ibuf++] = '\n'; 
     1588                            break; 
     1589                        case 'n': 
     1590                            buf[ibuf++] = '\n'; 
     1591                            break; 
     1592                        case 't': 
     1593                            buf[ibuf++] = '\t'; 
     1594                            break; 
     1595                        case 'v': 
     1596                            buf[ibuf++] = '\v'; 
     1597                            break; 
     1598                        case 'f': 
     1599                            buf[ibuf++] = '\f'; 
     1600                            break; 
     1601                        case '\\': 
     1602                        case '\'': 
     1603                        case '"': 
     1604                            buf[ibuf++] = str[i]; 
     1605                            break; 
     1606                        default: 
     1607                            //buf[ibuf++] = '\\'; 
     1608                            buf[ibuf++] = str[i]; 
     1609                            break; 
     1610                    } 
     1611                    inescape = false; 
     1612                } 
     1613                else 
     1614                { 
     1615                    switch(str[i]) 
     1616                    { 
     1617                        case '"': 
     1618                            break strloop; 
     1619                        case '\\': 
     1620                            inescape = true; 
     1621                            break; 
     1622                        default: 
     1623                            buf[ibuf++] = str[i]; 
     1624                    } 
     1625                } 
     1626            } 
     1627            return buf[0 .. ibuf]; 
     1628        } 
     1629         
     1630        void eatValues() 
     1631        { 
     1632            // Note: doesn't eat trailing ','. 
     1633            char[] s = nexttok(); 
     1634            int nbracks = 0; 
     1635            int nbraces = 0; 
     1636            if(s == "[") 
     1637            { 
     1638                nbracks++; 
     1639            } 
     1640            else if(s == "{") 
     1641            { 
     1642                nbraces++; 
     1643            } 
     1644            else 
     1645            { 
     1646                return; 
     1647            } 
     1648            assert(nbracks > 0 || nbraces > 0); 
     1649            for(;;) 
     1650            { 
     1651                s = nexttok(); 
     1652                if(!s.length) 
     1653                { 
     1654                    break; 
     1655                } 
     1656                if(s == "]") 
     1657                { 
     1658                    nbracks--; 
     1659                    assert(nbracks >= 0); 
     1660                    if(nbracks < 1 
     1661                        && nbraces < 1) 
     1662                    { 
     1663                        break; 
     1664                    } 
     1665                } 
     1666                else if(s == "}") 
     1667                { 
     1668                    nbraces--; 
     1669                    assert(nbraces >= 0); 
     1670                    if(nbraces < 1 
     1671                        && nbracks < 1) 
     1672                    { 
     1673                        break; 
     1674                    } 
     1675                } 
     1676                else if(s == "[") 
     1677                { 
     1678                    nbracks++; 
     1679                } 
     1680                else if(s == "{") 
     1681                { 
     1682                    nbraces++; 
     1683                } 
     1684            } 
     1685        } 
     1686         
     1687        char[128] _namebuf; 
     1688        char[] name = null; // Note: might refer to local memory. 
     1689        char[128] _typebuf; 
     1690        char[] type = null; // Note: might refer to local memory. 
     1691        ApiType kind = ApiType.UNKNOWN; 
     1692        ApiEntry* curae = null; 
     1693        char[128] _baseitembuf; 
     1694        char[] baseitem = null; // Note: might refer to local memory. 
     1695        ApiFlags attribs = ApiFlags.NONE; 
     1696        char[128] _commentbuf; 
     1697        char[] comment = null; // Note: might refer to local memory. 
     1698        ushort line = 0; 
     1699         
     1700        void resetall() 
     1701        { 
     1702            name = null; 
     1703            type = null; 
     1704            kind = ApiType.UNKNOWN; 
     1705            baseitem = null; 
     1706            attribs = ApiFlags.NONE; 
     1707            comment = null; 
     1708            curae = null; 
     1709            curscope = prevmodule; 
     1710            line = 0; 
     1711        } 
     1712         
     1713        void setcurae() 
     1714        { 
     1715            if(curae !is null) 
     1716            { 
     1717                curae.type = kind; 
     1718                curae.flags = attribs; 
     1719                if(null == curae.name) 
     1720                { 
     1721                    char[] name2 = cast(char[])mem(name.length)[0 .. name.length]; 
     1722                    name2[] = name; 
     1723                    curae.name = name2; 
     1724                } 
     1725                if(baseitem.length > 0) 
     1726                { 
     1727                    if(curae.type == ApiType.CLASS) 
     1728                    { 
     1729                        ApiClass* ac = cast(ApiClass*)curae; 
     1730                        if(null == ac.baseItemName) 
     1731                        { 
     1732                            ac.baseItemName = cast(char[])mem(baseitem.length)[0 .. baseitem.length]; 
     1733                            ac.baseItemName[] = baseitem; 
     1734                        } 
     1735                    } 
     1736                } 
     1737                if(type.length > 0) 
     1738                { 
     1739                    if(curae.type == ApiType.VAR) 
     1740                    { 
     1741                        ApiVar* av = cast(ApiVar*)curae; 
     1742                        av.itemRValue = cast(char[])mem(type.length)[0 .. type.length]; 
     1743                        av.itemRValue[] = type; 
     1744                    } 
     1745                    else if(curae.type == ApiType.FUNC) 
     1746                    { 
     1747                        char[] rvalue; 
     1748                        char[] sparams; 
     1749                        int i = 0; 
     1750                        for(; i < type.length; i++) 
     1751                        { 
     1752                            if('(' == type[i]) 
     1753                            { 
     1754                                rvalue = type[0 .. i]; 
     1755                                sparams = type[i .. $]; 
     1756                                break; 
     1757                            } 
     1758                            if(type[i] == '!') 
     1759                            { 
     1760                                // Parse past template args. 
     1761                                char[] targs = type[i + 1 .. $]; 
     1762                                ParenItem pitem; 
     1763                                if(!(ParamResult.DONE & nextParenItemStart(targs, pitem))) 
     1764                                { 
     1765                                    ParenItem tpi; 
     1766                                    while(!(ParamResult.DONE & nextParenItemNext(targs, tpi))) 
     1767                                    { 
     1768                                        // Make sure to skip to ')'. 
     1769                                    } 
     1770                                } 
     1771                                if(targs.ptr > type.ptr + i + 1) 
     1772                                { 
     1773                                    i = targs.ptr - type.ptr; 
     1774                                    assert(i >= 0); 
     1775                                    assert(i < type.length); 
     1776                                    i--; // Next loop iter will ++ again. 
     1777                                } 
     1778                            } 
     1779                        } 
     1780                        ApiFunc* af = cast(ApiFunc*)curae; 
     1781                        af.itemRValue = cast(char[])mem(rvalue.length)[0 .. rvalue.length]; 
     1782                        af.itemRValue[] = rvalue; 
     1783                        { 
     1784                            // Get params. 
     1785                            ParenItem pitem; 
     1786                            ParamResult pr; 
     1787                            pr = nextParenItemStart(sparams, pitem); 
     1788                            if(pr & ParamResult.VALID) 
     1789                            { 
     1790                                if(pitem.str.length <= ApiFuncArg.MAX_LENGTH) 
     1791                                { 
     1792                                    ApiFuncArg* lastarg; 
     1793                                    lastarg = cast(ApiFuncArg*)mem(ApiFuncArg.sizeof + pitem.str.length); 
     1794                                    lastarg.next = null; 
     1795                                    lastarg.length = pitem.str.length; 
     1796                                    lastarg.data.ptr[0 .. pitem.str.length] = pitem.str; 
     1797                                    af.args = lastarg; // First. 
     1798                                    while(pr & ParamResult.MORE) 
     1799                                    { 
     1800                                        pr = nextParenItemNext(sparams, pitem); 
     1801                                        if(!(pr & ParamResult.VALID)) 
     1802                                            break; 
     1803                                        if(pitem.str.length > ApiFuncArg.MAX_LENGTH) 
     1804                                        { 
     1805                                            af.args = null; 
     1806                                            break; 
     1807                                        } 
     1808                                        ApiFuncArg* arg; 
     1809                                        arg = cast(ApiFuncArg*)mem(ApiFuncArg.sizeof + pitem.str.length); 
     1810                                        arg.next = null; 
     1811                                        arg.length = pitem.str.length; 
     1812                                        arg.data.ptr[0 .. pitem.str.length] = pitem.str; 
     1813                                        lastarg.next = arg; 
     1814                                        lastarg = arg; 
     1815                                    } 
     1816                                } 
     1817                            } 
     1818                        } 
     1819                    } 
     1820                } 
     1821            } 
     1822        } 
     1823         
     1824        fieldloop: 
     1825        for(;;) 
     1826        { 
     1827            char[] stok = nexttok(); 
     1828            switch(stok) 
     1829            { 
     1830                case "\"name\"": 
     1831                case "\"n\"": 
     1832                    if(":" != nexttok()) 
     1833                    { 
     1834                        version(API_PICKY_JSON) 
     1835                            throw new Exception("Expected : in JSON (" ~ stok ~ ")"); 
     1836                        return; 
     1837                    } 
     1838                    { 
     1839                        char[] s = nexttok(); 
     1840                        if(s.length > _namebuf.length) 
     1841                        { 
     1842                            name = decodeString(s, new char[s.length]); 
     1843                        } 
     1844                        else 
     1845                        { 
     1846                            name = decodeString(s, _namebuf); 
     1847                        } 
     1848                        version(API_PICKY_JSON) 
     1849                        { 
     1850                            if(name.length < 1) 
     1851                            { 
     1852                                throw new Exception("name is empty in JSON; \"name\" : " ~ s); 
     1853                            } 
     1854                        } 
     1855                    } 
     1856                    break; 
     1857                case "\"type\"": 
     1858                case "\"t\"": 
     1859                    if(":" != nexttok()) 
     1860                    { 
     1861                        version(API_PICKY_JSON) 
     1862                            throw new Exception("Expected : in JSON (" ~ stok ~ ")"); 
     1863                        return; 
     1864                    } 
     1865                    { 
     1866                        char[] s = nexttok(); 
     1867                        if(s.length > _typebuf.length) 
     1868                        { 
     1869                            type = decodeString(s, new char[s.length]); 
     1870                        } 
     1871                        else 
     1872                        { 
     1873                            type = decodeString(s, _typebuf); 
     1874                        } 
     1875                    } 
     1876                    break; 
     1877                case "\"attributes\"": 
     1878                case "\"a\"": 
     1879                    if(":" != nexttok()) 
     1880                    { 
     1881                        version(API_PICKY_JSON) 
     1882                            throw new Exception("Expected : in JSON (" ~ stok ~ ")"); 
     1883                        return; 
     1884                    } 
     1885                    { 
     1886                        //eatValues(); 
     1887                        if("[" != nexttok()) 
     1888                        { 
     1889                            throw new Exception("Expected [ for \"attributes\" in JSON"); 
     1890                            return; 
     1891                        } 
    13801892                         
    1381                         curmodule = parentbuf[0 .. s.length]; 
    1382                         curmodule[] = s; 
    1383                         parentbuf[curmodule.length] = '.'; 
     1893                        attribloop: 
     1894                        for(;;) 
     1895                        { 
     1896                            char[] s = nexttok(); 
     1897                            switch(s) 
     1898                            { 
     1899                                case "\"protected\"": 
     1900                                    attribs |= ApiFlags.PROTECTED; 
     1901                                    break; 
     1902                                case "\"const\"": 
     1903                                    attribs |= ApiFlags.CONST; 
     1904                                    break; 
     1905                                case "\"static\"": 
     1906                                    attribs |= ApiFlags.STATIC; 
     1907                                    break; 
     1908                                case "\"final\"": 
     1909                                    attribs |= ApiFlags.FINAL; 
     1910                                    break; 
     1911                                case "\"auto\"": 
     1912                                    attribs |= ApiFlags.AUTO; 
     1913                                    break; 
     1914                                case "\"deprecated\"": 
     1915                                    attribs |= ApiFlags.DEPRECATED; 
     1916                                    break; 
     1917                                case "\"package\"": 
     1918                                    attribs |= ApiFlags.PACKAGE; 
     1919                                    break; 
     1920                                case "\"private\"": 
     1921                                    attribs |= ApiFlags.PRIVATE; 
     1922                                    break; 
     1923                                case ",": 
     1924                                    break; 
     1925                                case "": 
     1926                                case "]": 
     1927                                    break attribloop; 
     1928                                default: 
     1929                                    break; 
     1930                            } 
     1931                        } 
     1932                    } 
     1933                    break; 
     1934                case "\"base\"": 
     1935                case "\"b\"": 
     1936                    // Base class. 
     1937                    if(":" != nexttok()) 
     1938                    { 
     1939                        version(API_PICKY_JSON) 
     1940                            throw new Exception("Expected : in JSON (" ~ stok ~ ")"); 
     1941                        return; 
     1942                    } 
     1943                    { 
     1944                        char[] s = nexttok(); 
     1945                        if(s.length > _baseitembuf.length) 
     1946                        { 
     1947                            baseitem = decodeString(s, new char[s.length]); 
     1948                        } 
     1949                        else 
     1950                        { 
     1951                            baseitem = decodeString(s, _baseitembuf); 
     1952                        } 
     1953                    } 
     1954                    break; 
     1955                case "\"line\"": 
     1956                case "\"l\"": 
     1957                    if(":" != nexttok()) 
     1958                    { 
     1959                        version(API_PICKY_JSON) 
     1960                            throw new Exception("Expected : in JSON (" ~ stok ~ ")"); 
     1961                        return; 
     1962                    } 
     1963                    { 
     1964                        char[] sline = nexttok(); 
     1965                        /+try 
     1966                        { 
     1967                            line = std.conv.toUshort(sline); 
     1968                        } 
     1969                        catch 
     1970                        { 
     1971                        }+/ 
     1972                    } 
     1973                    break; 
     1974                case "\"kind\"": 
     1975                case "\"k\"": 
     1976                    if(":" != nexttok()) 
     1977                    { 
     1978                        version(API_PICKY_JSON) 
     1979                            throw new Exception("Expected : in JSON (" ~ stok ~ ")"); 
     1980                        return; 
     1981                    } 
     1982                    if(name.length < 1) 
     1983                    { 
     1984                        version(API_PICKY_JSON) 
     1985                            throw new Exception("name must be specified before kind in JSON"); 
     1986                        nexttok(); 
     1987                        break; 
     1988                    } 
     1989                    switch(nexttok()) 
     1990                    { 
     1991                        case "\"module\"": 
     1992                        case "\"m\"": 
     1993                            kind = ApiType.MODULE; 
     1994                            { 
     1995                                if(name.length >= parentbuf.length - 128) 
     1996                                    errmodpath(); 
     1997                                 
     1998                                curscope = parentbuf[0 .. name.length]; 
     1999                                curscope[] = name; 
     2000                                parentbuf[curscope.length] = '.'; 
     2001                                 
     2002                                ApiModule* ae = cast(ApiModule*)mem(ApiModule.sizeof); 
     2003                                *ae = ApiModule.init; 
     2004                                curae = ae.entry; 
     2005                                setcurae(); 
     2006                                int i = std.string.rfind(ae.entry.name, '.'); 
     2007                                string pkg = ""; 
     2008                                if(i != -1) 
     2009                                { 
     2010                                    pkg = ae.entry.name[0 .. i]; // Packages. 
     2011                                    ae.entry.name = ae.entry.name[i + 1 .. $]; 
     2012                                    //ae.entry.parent = pkg; 
     2013                                } 
     2014                                api.addApiModule(pkg, ae, { return cast(ApiPackage*)mem(ApiPackage.sizeof); }); 
     2015                            } 
     2016                            break; 
     2017                        case "\"alias\"": 
     2018                        case "\"a\"": 
     2019                            kind = ApiType.UNKNOWN; // Hmm. 
     2020                            break; 
     2021                        case "\"interface\"": 
     2022                        case "\"i\"": 
     2023                            kind = ApiType.INTERFACE; 
     2024                            { 
     2025                                if(!curscope.length) 
     2026                                    break; 
     2027                                assert('.' == parentbuf[curscope.length]); 
     2028                                 
     2029                                ApiInterface* ai; 
     2030                                ai = cast(ApiInterface*)mem(ApiInterface.sizeof); 
     2031                                *ai = ApiInterface.init; 
     2032                                curae = ai.entry; 
     2033                                setcurae(); 
     2034                                char[] myscope = curscope; 
     2035                                { 
     2036                                    if(curscope.length + 1 + name.length + 1 > parentbuf.length) 
     2037                                        errmodpath(); 
     2038                                    parentbuf[curscope.length + 1 .. curscope.length + 1 + name.length] = name; 
     2039                                    curscope = parentbuf[0 .. curscope.length + 1 + name.length]; // Scope for members. 
     2040                                    parentbuf[curscope.length] = '.'; 
     2041                                } 
     2042                                //("Adding interface '" ~ ai.entry.name ~ "' to scope '" ~ myscope ~ "'"); 
     2043                                api.addApiInterface(myscope, ai); 
     2044                            } 
     2045                            break; 
     2046                        case "\"union\"": 
     2047                        case "\"u\"": 
     2048                            kind = ApiType.UNION; 
     2049                            { 
     2050                                if(!curscope.length) 
     2051                                    break; 
     2052                                assert('.' == parentbuf[curscope.length]); 
     2053                                 
     2054                                ApiUnion* au; 
     2055                                au = cast(ApiUnion*)mem(ApiUnion.sizeof); 
     2056                                *au = ApiUnion.init; 
     2057                                curae = au.entry; 
     2058                                setcurae(); 
     2059                                char[] myscope = curscope; 
     2060                                { 
     2061                                    if(curscope.length + 1 + name.length + 1 > parentbuf.length) 
     2062                                        errmodpath(); 
     2063                                    parentbuf[curscope.length + 1 .. curscope.length + 1 + name.length] = name; 
     2064                                    curscope = parentbuf[0 .. curscope.length + 1 + name.length]; // Scope for members. 
     2065                                    parentbuf[curscope.length] = '.'; 
     2066                                } 
     2067                                api.addApiUnion(myscope, au); 
     2068                            } 
     2069                            break; 
     2070                        case "\"struct\"": 
     2071                        case "\"s\"": 
     2072                            kind = ApiType.STRUCT; 
     2073                            { 
     2074                                if(!curscope.length) 
     2075                                    break; 
     2076                                assert('.' == parentbuf[curscope.length]); 
     2077                                 
     2078                                ApiStruct* as; 
     2079                                as = cast(ApiStruct*)mem(ApiStruct.sizeof); 
     2080                                *as = ApiStruct.init; 
     2081                                curae = as.entry; 
     2082                                setcurae(); 
     2083                                char[] myscope = curscope; 
     2084                                { 
     2085                                    if(curscope.length + 1 + name.length + 1 > parentbuf.length) 
     2086                                        errmodpath(); 
     2087                                    parentbuf[curscope.length + 1 .. curscope.length + 1 + name.length] = name; 
     2088                                    curscope = parentbuf[0 .. curscope.length + 1 + name.length]; // Scope for members. 
     2089                                    parentbuf[curscope.length] = '.'; 
     2090                                } 
     2091                                api.addApiStruct(myscope, as); 
     2092                            } 
     2093                            break; 
     2094                        case "\"class\"": 
     2095                        case "\"c\"": 
     2096                            kind = ApiType.CLASS; 
     2097                            { 
     2098                                if(!curscope.length) 
     2099                                    break; 
     2100                                assert('.' == parentbuf[curscope.length]); 
     2101                                 
     2102                                ApiClass* ac; 
     2103                                ac = cast(ApiClass*)mem(ApiClass.sizeof); 
     2104                                *ac = ApiClass.init; 
     2105                                curae = ac.entry; 
     2106                                setcurae(); 
     2107                                char[] myscope = curscope; 
     2108                                { 
     2109                                    if(curscope.length + 1 + name.length + 1 > parentbuf.length) 
     2110                                        errmodpath(); 
     2111                                    parentbuf[curscope.length + 1 .. curscope.length + 1 + name.length] = name; 
     2112                                    curscope = parentbuf[0 .. curscope.length + 1 + name.length]; // Scope for members. 
     2113                                    parentbuf[curscope.length] = '.'; 
     2114                                } 
     2115                                api.addApiClass(myscope, ac); 
     2116                            } 
     2117                            break; 
     2118                        case "\"constructor\"": 
     2119                            kind = ApiType.FUNC; // Constructor->function. 
     2120                        case "\"destructor\"": 
     2121                            kind = ApiType.FUNC; // Destructor->function. 
     2122                        case "\"function\"": 
     2123                        case "\"f\"": 
     2124                            kind = ApiType.FUNC; 
     2125                            { 
     2126                                if(!curscope.length) 
     2127                                    break; 
     2128                                assert('.' == parentbuf[curscope.length]); 
     2129                                 
     2130                                ApiFunc* af; 
     2131                                af = cast(ApiFunc*)mem(ApiFunc.sizeof); 
     2132                                *af = ApiFunc.init; 
     2133                                curae = af.entry; 
     2134                                setcurae(); 
     2135                                char[] myscope = curscope; 
     2136                                { 
     2137                                    if(curscope.length + 1 + name.length + 1 > parentbuf.length) 
     2138                                        errmodpath(); 
     2139                                    parentbuf[curscope.length + 1 .. curscope.length + 1 + name.length] = name; 
     2140                                    curscope = parentbuf[0 .. curscope.length + 1 + name.length]; // Scope for members. 
     2141                                    parentbuf[curscope.length] = '.'; 
     2142                                } 
     2143                                api.addApiFunc(myscope, af); 
     2144                            } 
     2145                            break; 
     2146                        case "\"variable\"": 
     2147                        case "\"v\"": 
     2148                            kind = ApiType.VAR; 
     2149                            { 
     2150                                if(!curscope.length) 
     2151                                    break; 
     2152                                assert('.' == parentbuf[curscope.length]); 
     2153                                 
     2154                                ApiVar* av; 
     2155                                av = cast(ApiVar*)mem(ApiVar.sizeof); 
     2156                                *av = ApiVar.init; 
     2157                                curae = av.entry; 
     2158                                setcurae(); 
     2159                                char[] myscope = curscope; 
     2160                                { 
     2161                                    if(curscope.length + 1 + name.length + 1 > parentbuf.length) 
     2162                                        errmodpath(); 
     2163                                    parentbuf[curscope.length + 1 .. curscope.length + 1 + name.length] = name; 
     2164                                    curscope = parentbuf[0 .. curscope.length + 1 + name.length]; // Scope for members. 
     2165                                    parentbuf[curscope.length] = '.'; 
     2166                                } 
     2167                                api.addApiVar(myscope, av); 
     2168                            } 
     2169                            break; 
     2170                        case "\"enum\"": 
     2171                        case "\"e\"": 
     2172                            kind = ApiType.ENUM; 
     2173                            { 
     2174                                if(!curscope.length) 
     2175                                    break; 
     2176                                assert('.' == parentbuf[curscope.length]); 
     2177                                 
     2178                                ApiEnum* ae; 
     2179                                ae = cast(ApiEnum*)mem(ApiEnum.sizeof); 
     2180                                *ae = ApiEnum.init; 
     2181                                curae = ae.entry; 
     2182                                setcurae(); 
     2183                                char[] myscope = curscope; 
     2184                                { 
     2185                                    if(curscope.length + 1 + name.length + 1 > parentbuf.length) 
     2186                                        errmodpath(); 
     2187                                    parentbuf[curscope.length + 1 .. curscope.length + 1 + name.length] = name; 
     2188                                    curscope = parentbuf[0 .. curscope.length + 1 + name.length]; // Scope for members. 
     2189                                    parentbuf[curscope.length] = '.'; 
     2190                                } 
     2191                                api.addApiEnum(myscope, ae); 
     2192                            } 
     2193                            break; 
     2194                        case "\"enum member\"": 
     2195                        case "\"ev\"": 
     2196                            kind = ApiType.ENUMVALUE; 
     2197                            { 
     2198                                if(!curscope.length) 
     2199                                    break; 
     2200                                assert('.' == parentbuf[curscope.length]); 
     2201                                 
     2202                                ApiEnumValue* ae; 
     2203                                ae = cast(ApiEnumValue*)mem(ApiEnumValue.sizeof); 
     2204                                *ae = ApiEnumValue.init; 
     2205                                curae = ae.entry; 
     2206                                setcurae(); 
     2207                                char[] myscope = curscope; 
     2208                                api.addApiEnumValue(myscope, ae); 
     2209                            } 
     2210                            break; 
     2211                        default: ; 
     2212                    } 
     2213                    break; 
     2214                case "\"members\"": 
     2215                case "\"m\"": 
     2216                    if(":" != nexttok()) 
     2217                    { 
     2218                        version(API_PICKY_JSON) 
     2219                            throw new Exception("Expected : in JSON (" ~ stok ~ ")"); 
     2220                        return; 
     2221                    } 
     2222                    if("[" != nexttok()) 
     2223                    { 
     2224                        throw new Exception("Expected [ for \"members\" in JSON"); 
     2225                        return; 
     2226                    } 
     2227                    _jsonLoadMembers(nexttok); 
     2228                    curscope = prevmodule; 
     2229                    break; 
     2230                case "\"comment\"": 
     2231                case "\"c\"": 
     2232                    if(":" != nexttok()) 
     2233                    { 
     2234                        version(API_PICKY_JSON) 
     2235                            throw new Exception("Expected : in JSON (" ~ stok ~ ")"); 
     2236                        return; 
     2237                    } 
     2238                    { 
     2239                        char[] s = nexttok(); 
     2240                        if(s.length > _commentbuf.length) 
     2241                        { 
     2242                            comment = decodeString(s, new char[s.length]); 
     2243                        } 
     2244                        else 
     2245                        { 
     2246                            comment = decodeString(s, _commentbuf); 
     2247                        } 
     2248                    } 
     2249                    break; 
     2250                case "]": 
     2251                    break fieldloop; 
     2252                case ",": 
     2253                    break; 
     2254                case "}": 
     2255                    // Save current member. 
     2256                    setcurae(); 
     2257                    if(curae != null) 
     2258                    { 
     2259                        if(comment is null) 
     2260                        { 
     2261                            //curae.flags |= ApiFlags.PRIVATE; 
     2262                            curae.flags |= ApiFlags.UNDOCUMENTED; 
     2263                        } 
     2264                        else if(curae.type == ApiType.FUNC) 
     2265                        { 
     2266                            if(-1 != std.string.find(comment, "@getter")) 
     2267                            { 
     2268                                ApiFunc* af = cast(ApiFunc*)curae; 
     2269                                af.functype = ApiFunc.GETTER; 
     2270                            } 
     2271                            else if(-1 != std.string.find(comment, "@setter")) 
     2272                            { 
     2273                                ApiFunc* af = cast(ApiFunc*)curae; 
     2274                                af.functype = ApiFunc.SETTER; 
     2275                            } 
     2276                        } 
     2277                    } 
     2278                    // Reset for new member. 
     2279                    resetall(); 
     2280                    break; 
     2281                case "{": 
     2282                    // New member. 
     2283                    break; 
     2284                default: 
     2285                    if(stok.length > 0 && '"' == stok[0]) 
     2286                    { 
     2287                        if(":" != nexttok()) 
     2288                        { 
     2289                            version(API_PICKY_JSON) 
     2290                                throw new Exception("Expected : in JSON (" ~ stok ~ ")"); 
     2291                            return; 
     2292                        } 
     2293                        eatValues(); 
     2294                    } 
     2295                    else 
     2296                    { 
     2297                        version(API_PICKY_JSON) 
     2298                        { 
     2299                            char[] nstok = nexttok(); 
     2300                            if(nstok.length) 
     2301                                throw new Exception("JSON error, unexpected " ~ stok ~ " " ~ nstok); 
     2302                        } 
     2303                        break fieldloop; 
     2304                    } 
     2305            } 
     2306        } 
     2307    } 
     2308     
     2309     
     2310    void _dapiLoadLine(char[] line) 
     2311    { 
     2312        char[] s, s2; 
     2313        int i; 
     2314        { 
     2315            switch(nextWord(line)) 
     2316            { 
     2317                case "module": 
     2318                    { 
     2319                        s = nextWord(line); 
     2320                        if(s.length) 
     2321                        { 
     2322                            if(s.length >= parentbuf.length - 128) 
     2323                                errmodpath(); 
     2324                             
     2325                            curscope = parentbuf[0 .. s.length]; 
     2326                            curscope[] = s; 
     2327                            parentbuf[curscope.length] = '.'; 
     2328                             
     2329                            s2 = cast(char[])mem(s.length)[0 .. s.length]; 
     2330                            s2[] = s; 
     2331                            ApiModule* ae; 
     2332                            ae = cast(ApiModule*)mem(ApiModule.sizeof); 
     2333                            *ae = ApiModule.init; 
     2334                            ae.entry.type = ApiType.MODULE; 
     2335                            ae.entry.name = s2; 
     2336                            s = null; 
     2337                            i = std.string.rfind(s2, '.'); 
     2338                            if(i != -1) 
     2339                            { 
     2340                                s = s2[0 .. i]; // Packages. 
     2341                                ae.entry.name = s2[i + 1 .. s2.length]; 
     2342                                //ae.entry.parent = s; 
     2343                            } 
     2344                            api.addApiModule(s, ae, { return cast(ApiPackage*)mem(ApiPackage.sizeof); }); 
     2345                        } 
     2346                    } 
     2347                    break; 
     2348                 
     2349                case "class": 
     2350                    { 
     2351                        if(!curscope.length) 
     2352                            break; 
     2353                        assert('.' == parentbuf[curscope.length]); 
    13842354                         
    1385                         s2 = cast(char[])mem(s.length)[0 .. s.length]; 
    1386                         s2[] = s; 
    1387                         ApiModule* ae; 
    1388                         ae = cast(ApiModule*)mem(ApiModule.sizeof); 
    1389                         *ae = ApiModule.init; 
    1390                         ae.entry.type = ApiType.MODULE; 
    1391                         ae.entry.name = s2; 
    1392                         s = null; 
    1393                         i = std.string.rfind(s2, '.'); 
    1394                         if(i != -1) 
    1395                         { 
    1396                             s = s2[0 .. i]; // Packages. 
    1397                             ae.entry.name = s2[i + 1 .. s2.length]; 
    1398                             //ae.entry.parent = s; 
    1399                         } 
    1400                         api.addApiModule(s, ae, { return cast(ApiPackage*)mem(ApiPackage.sizeof); }); 
    1401                     } 
    1402                 } 
    1403                 break; 
    1404              
    1405             case "class": 
    1406                 { 
    1407                     if(!curmodule.length) 
    1408                         break; 
    1409                     assert('.' == parentbuf[curmodule.length]); 
    1410                      
    1411                     char[] flagstr; 
    1412                     flagstr = nextWord(line); 
    1413                     char[] path; 
    1414                     path = nextWord(line); 
    1415                     char[] ename; 
    1416                     ename = nextWord(line); 
    1417                     char[] basename; 
    1418                     basename = nextWord(line); 
    1419                     ApiClass* ac; 
    1420                     ac = cast(ApiClass*)mem(ApiClass.sizeof); 
    1421                     *ac = ApiClass.init; 
    1422                     ac.entry.type = ApiType.CLASS; 
    1423                     ac.name = cast(char[])mem(ename.length)[0 .. ename.length]; 
    1424                     ac.name[] = ename; 
    1425                     s2 = curmodule; 
    1426                     if("-" != path && "." != path) 
    1427                     { 
    1428                         //ac.parent = path; 
    1429                         if(curmodule.length + 1 + path.length > parentbuf.length) 
    1430                             errmodpath(); 
    1431                         parentbuf[curmodule.length + 1 .. curmodule.length + 1 + path.length] = path; 
    1432                         s2 = parentbuf[0 .. curmodule.length + 1 + path.length]; 
    1433                     } 
    1434                     if(basename.length && "-" != basename) 
    1435                     { 
    1436                         //ac.baseItemName = basename; 
    1437                         ac.baseItemName = cast(char[])mem(basename.length)[0 .. basename.length]; 
    1438                         ac.baseItemName[0 .. basename.length] = basename; 
    1439                     } 
    1440                     ac.flags = parseDApiFlags(flagstr); 
    1441                     api.addApiClass(s2, ac); 
    1442                 } 
    1443                 break; 
    1444              
    1445             case "struct": 
    1446                 { 
    1447                     if(!curmodule.length) 
    1448                         break; 
    1449                     assert('.' == parentbuf[curmodule.length]); 
    1450                      
    1451                     char[] flagstr; 
    1452                     flagstr = nextWord(line); 
    1453                     char[] path; 
    1454                     path = nextWord(line); 
    1455                     char[] ename; 
    1456                     ename = nextWord(line); 
    1457                     ApiStruct* as; 
    1458                     as = cast(ApiStruct*)mem(ApiStruct.sizeof); 
    1459                     *as = ApiStruct.init; 
    1460                     as.entry.type = ApiType.STRUCT; 
    1461                     as.name = cast(char[])mem(ename.length)[0 .. ename.length]; 
    1462                     as.name[] = ename; 
    1463                     s2 = curmodule; 
    1464                     if("-" != path && "." != path) 
    1465                     { 
    1466                         //as.parent = path; 
    1467                         if(curmodule.length + 1 + path.length > parentbuf.length) 
    1468                             errmodpath(); 
    1469                         parentbuf[curmodule.length + 1 .. curmodule.length + 1 + path.length] = path; 
    1470                         s2 = parentbuf[0 .. curmodule.length + 1 + path.length]; 
    1471                     } 
    1472                     as.flags = parseDApiFlags(flagstr); 
    1473                     api.addApiStruct(s2, as); 
    1474                 } 
    1475                 break; 
    1476              
    1477             case "interface": 
    1478                 { 
    1479                     if(!curmodule.length) 
    1480                         break; 
    1481                     assert('.' == parentbuf[curmodule.length]); 
    1482                      
    1483                     char[] flagstr; 
    1484                     flagstr = nextWord(line); 
    1485                     char[] path; 
    1486                     path = nextWord(line); 
    1487                     char[] ename; 
    1488                     ename = nextWord(line); 
    1489                     ApiInterface* ai; 
    1490                     ai = cast(ApiInterface*)mem(ApiInterface.sizeof); 
    1491                     *ai = ApiInterface.init; 
    1492                     ai.entry.type = ApiType.INTERFACE; 
    1493                     ai.name = cast(char[])mem(ename.length)[0 .. ename.length]; 
    1494                     ai.name[] = ename; 
    1495                     s2 = curmodule; 
    1496                     if("-" != path && "." != path) 
    1497                     { 
    1498                         //ai.parent = path; 
    1499                         if(curmodule.length + 1 + path.length > parentbuf.length) 
    1500                             errmodpath(); 
    1501                         parentbuf[curmodule.length + 1 .. curmodule.length + 1 + path.length] = path; 
    1502                         s2 = parentbuf[0 .. curmodule.length + 1 + path.length]; 
    1503                     } 
    1504                     ai.flags = parseDApiFlags(flagstr); 
    1505                     api.addApiInterface(s2, ai); 
    1506                 } 
    1507                 break; 
    1508              
    1509             case "union": 
    1510                 { 
    1511                     if(!curmodule.length) 
    1512                         break; 
    1513                     assert('.' == parentbuf[curmodule.length]); 
    1514                      
    1515                     char[] flagstr; 
    1516                     flagstr = nextWord(line); 
    1517                     char[] path; 
    1518                     path = nextWord(line); 
    1519                     char[] ename; 
    1520                     ename = nextWord(line); 
    1521                     ApiUnion* au; 
    1522                     au = cast(ApiUnion*)mem(ApiUnion.sizeof); 
    1523                     *au = ApiUnion.init; 
    1524                     au.entry.type = ApiType.UNION; 
    1525                     au.name = cast(char[])mem(ename.length)[0 .. ename.length]; 
    1526                     au.name[] = ename; 
    1527                     s2 = curmodule; 
    1528                     if("-" != path && "." != path) 
    1529                     { 
    1530                         //au.parent = path; 
    1531                         if(curmodule.length + 1 + path.length > parentbuf.length) 
    1532                             errmodpath(); 
    1533                         parentbuf[curmodule.length + 1 .. curmodule.length + 1 + path.length] = path; 
    1534                         s2 = parentbuf[0 .. curmodule.length + 1 + path.length]; 
    1535                     } 
    1536                     au.flags = parseDApiFlags(flagstr); 
    1537                     api.addApiUnion(s2, au); 
    1538                 } 
    1539                 break; 
    1540              
    1541             case "getter": 
    1542                 i = ApiFunc.GETTER; 
    1543                 goto in_func; 
    1544             case "setter": 
    1545                 i = ApiFunc.SETTER; 
    1546                 goto in_func; 
    1547             case "func": 
    1548                 i = ApiFunc.FUNC; 
    1549                 in_func: 
    1550                 { 
    1551                     if(!curmodule.length) 
    1552                         break; 
    1553                     assert('.' == parentbuf[curmodule.length]); 
    1554                      
    1555                     char[] flagstr; 
    1556                     flagstr = nextWord(line); 
    1557                     char[] path; 
    1558                     path = nextWord(line); 
    1559                     char[] ename; 
    1560                     ename = nextWord(line); 
    1561                     ParenItem pitem; 
    1562                     if(!(ParamResult.DONE & nextParenItemStart(line, pitem))) 
    1563                     { 
    1564                         ParenItem tpi; 
    1565                         while(!(ParamResult.DONE & nextParenItemNext(line, tpi))) 
    1566                         { 
    1567                             // Make sure to skip to ')'. 
    1568                         } 
    1569                     } 
    1570                     ApiFunc* af; 
    1571                     af = cast(ApiFunc*)mem(ApiFunc.sizeof); 
    1572                     *af = ApiFunc.init; 
    1573                     af.type = ApiType.FUNC; 
    1574                     af.functype = i; 
    1575                     af.name = cast(char[])mem(ename.length)[0 .. ename.length]; 
    1576                     af.name[] = ename; 
    1577                     s2 = curmodule; 
    1578                     if("-" != path && "." != path) 
    1579                     { 
    1580                         //af.parent = path; 
    1581                         if(curmodule.length + 1 + path.length > parentbuf.length) 
    1582                             errmodpath(); 
    1583                         parentbuf[curmodule.length + 1 .. curmodule.length + 1 + path.length] = path; 
    1584                         s2 = parentbuf[0 .. curmodule.length + 1 + path.length]; 
    1585                     } 
    1586                     af.flags = parseDApiFlags(flagstr); 
    1587                     //af.itemRValue = pitem.str.dup; 
    1588                     af.itemRValue = cast(char[])mem(pitem.str.length)[0 .. pitem.str.length]; 
    1589                     af.itemRValue[] = pitem.str; 
    1590                     // Get params. 
    1591                     ParamResult pr; 
    1592                     pr = nextParenItemStart(line, pitem); 
    1593                     if(pr & ParamResult.VALID) 
    1594                     { 
    1595                         if(pitem.str.length <= ApiFuncArg.length.max) 
    1596                         { 
    1597                             ApiFuncArg* lastarg; 
    1598                             lastarg = cast(ApiFuncArg*)mem(ApiFuncArg.sizeof + pitem.str.length); 
    1599                             lastarg.next = null; 
    1600                             lastarg.length = pitem.str.length; 
    1601                             lastarg.data.ptr[0 .. pitem.str.length] = pitem.str; 
    1602                             af.args = lastarg; // First. 
    1603                             while(pr & ParamResult.MORE) 
     2355                        char[] flagstr; 
     2356                        flagstr = nextWord(line); 
     2357                        char[] path; 
     2358                        path = nextWord(line); 
     2359                        char[] ename; 
     2360                        ename = nextWord(line); 
     2361                        char[] basename; 
     2362                        basename = nextWord(line); 
     2363                        ApiClass* ac; 
     2364                        ac = cast(ApiClass*)mem(ApiClass.sizeof); 
     2365                        *ac = ApiClass.init; 
     2366                        ac.entry.type = ApiType.CLASS; 
     2367                        ac.name = cast(char[])mem(ename.length)[0 .. ename.length]; 
     2368                        ac.name[] = ename; 
     2369                        s2 = curscope; 
     2370                        if("-" != path && "." != path) 
     2371                        { 
     2372                            //ac.parent = path; 
     2373                            if(curscope.length + 1 + path.length > parentbuf.length) 
     2374                                errmodpath(); 
     2375                            parentbuf[curscope.length + 1 .. curscope.length + 1 + path.length] = path; 
     2376                            s2 = parentbuf[0 .. curscope.length + 1 + path.length]; 
     2377                        } 
     2378                        if(basename.length && "-" != basename) 
     2379                        { 
     2380                            //ac.baseItemName = basename; 
     2381                            ac.baseItemName = cast(char[])mem(basename.length)[0 .. basename.length]; 
     2382                            ac.baseItemName[0 .. basename.length] = basename; 
     2383                        } 
     2384                        ac.flags = parseDApiFlags(flagstr); 
     2385                        api.addApiClass(s2, ac); 
     2386                    } 
     2387                    break; 
     2388                 
     2389                case "struct": 
     2390                    { 
     2391                        if(!curscope.length) 
     2392                            break; 
     2393                        assert('.' == parentbuf[curscope.length]); 
     2394                         
     2395                        char[] flagstr; 
     2396                        flagstr = nextWord(line); 
     2397                        char[] path; 
     2398                        path = nextWord(line); 
     2399                        char[] ename; 
     2400                        ename = nextWord(line); 
     2401                        ApiStruct* as; 
     2402                        as = cast(ApiStruct*)mem(ApiStruct.sizeof); 
     2403                        *as = ApiStruct.init; 
     2404                        as.entry.type = ApiType.STRUCT; 
     2405                        as.name = cast(char[])mem(ename.length)[0 .. ename.length]; 
     2406                        as.name[] = ename; 
     2407                        s2 = curscope; 
     2408                        if("-" != path && "." != path) 
     2409                        { 
     2410                            //as.parent = path; 
     2411                            if(curscope.length + 1 + path.length > parentbuf.length) 
     2412                                errmodpath(); 
     2413                            parentbuf[curscope.length + 1 .. curscope.length + 1 + path.length] = path; 
     2414                            s2 = parentbuf[0 .. curscope.length + 1 + path.length]; 
     2415                        } 
     2416                        as.flags = parseDApiFlags(flagstr); 
     2417                        api.addApiStruct(s2, as); 
     2418                    } 
     2419                    break; 
     2420                 
     2421                case "interface": 
     2422                    { 
     2423                        if(!curscope.length) 
     2424                            break; 
     2425                        assert('.' == parentbuf[curscope.length]); 
     2426                         
     2427                        char[] flagstr; 
     2428                        flagstr = nextWord(line); 
     2429                        char[] path; 
     2430                        path = nextWord(line); 
     2431                        char[] ename; 
     2432                        ename = nextWord(line); 
     2433                        ApiInterface* ai; 
     2434                        ai = cast(ApiInterface*)mem(ApiInterface.sizeof); 
     2435                        *ai = ApiInterface.init; 
     2436                        ai.entry.type = ApiType.INTERFACE; 
     2437                        ai.name = cast(char[])mem(ename.length)[0 .. ename.length]; 
     2438                        ai.name[] = ename; 
     2439                        s2 = curscope; 
     2440                        if("-" != path && "." != path) 
     2441                        { 
     2442                            //ai.parent = path; 
     2443                            if(curscope.length + 1 + path.length > parentbuf.length) 
     2444                                errmodpath(); 
     2445                            parentbuf[curscope.length + 1 .. curscope.length + 1 + path.length] = path; 
     2446                            s2 = parentbuf[0 .. curscope.length + 1 + path.length]; 
     2447                        } 
     2448                        ai.flags = parseDApiFlags(flagstr); 
     2449                        api.addApiInterface(s2, ai); 
     2450                    } 
     2451                    break; 
     2452                 
     2453                case "union": 
     2454                    { 
     2455                        if(!curscope.length) 
     2456                            break; 
     2457                        assert('.' == parentbuf[curscope.length]); 
     2458                         
     2459                        char[] flagstr; 
     2460                        flagstr = nextWord(line); 
     2461                        char[] path; 
     2462                        path = nextWord(line); 
     2463                        char[] ename; 
     2464                        ename = nextWord(line); 
     2465                        ApiUnion* au; 
     2466                        au = cast(ApiUnion*)mem(ApiUnion.sizeof); 
     2467                        *au = ApiUnion.init; 
     2468                        au.entry.type = ApiType.UNION; 
     2469                        au.name = cast(char[])mem(ename.length)[0 .. ename.length]; 
     2470                        au.name[] = ename; 
     2471                        s2 = curscope; 
     2472                        if("-" != path && "." != path) 
     2473                        { 
     2474                            //au.parent = path; 
     2475                            if(curscope.length + 1 + path.length > parentbuf.length) 
     2476                                errmodpath(); 
     2477                            parentbuf[curscope.length + 1 .. curscope.length + 1 + path.length] = path; 
     2478                            s2 = parentbuf[0 .. curscope.length + 1 + path.length]; 
     2479                        } 
     2480                        au.flags = parseDApiFlags(flagstr); 
     2481                        api.addApiUnion(s2, au); 
     2482                    } 
     2483                    break; 
     2484                 
     2485                case "getter": 
     2486                    i = ApiFunc.GETTER; 
     2487                    goto in_func; 
     2488                case "setter": 
     2489                    i = ApiFunc.SETTER; 
     2490                    goto in_func; 
     2491                case "func": 
     2492                    i = ApiFunc.FUNC; 
     2493                    in_func: 
     2494                    { 
     2495                        if(!curscope.length) 
     2496                            break; 
     2497                        assert('.' == parentbuf[curscope.length]); 
     2498                         
     2499                        char[] flagstr; 
     2500                        flagstr = nextWord(line); 
     2501                        char[] path; 
     2502                        path = nextWord(line); 
     2503                        char[] ename; 
     2504                        ename = nextWord(line); 
     2505                        ParenItem pitem; 
     2506                        if(!(ParamResult.DONE & nextParenItemStart(line, pitem))) 
     2507                        { 
     2508                            ParenItem tpi; 
     2509                            while(!(ParamResult.DONE & nextParenItemNext(line, tpi))) 
    16042510                            { 
    1605                                 pr = nextParenItemNext(line, pitem); 
    1606                                 if(!(pr & ParamResult.VALID)) 
    1607                                     break; 
    1608                                 if(pitem.str.length > ApiFuncArg.length.max) 
     2511                                // Make sure to skip to ')'. 
     2512                            } 
     2513                        } 
     2514                        ApiFunc* af; 
     2515                        af = cast(ApiFunc*)mem(ApiFunc.sizeof); 
     2516                        *af = ApiFunc.init; 
     2517                        af.type = ApiType.FUNC; 
     2518                        af.functype = i; 
     2519                        af.name = cast(char[])mem(ename.length)[0 .. ename.length]; 
     2520                        af.name[] = ename; 
     2521                        s2 = curscope; 
     2522                        if("-" != path && "." != path) 
     2523                        { 
     2524                            //af.parent = path; 
     2525                            if(curscope.length + 1 + path.length > parentbuf.length) 
     2526                                errmodpath(); 
     2527                            parentbuf[curscope.length + 1 .. curscope.length + 1 + path.length] = path; 
     2528                            s2 = parentbuf[0 .. curscope.length + 1 + path.length]; 
     2529                        } 
     2530                        af.flags = parseDApiFlags(flagstr); 
     2531                        //af.itemRValue = pitem.str.dup; 
     2532                        af.itemRValue = cast(char[])mem(pitem.str.length)[0 .. pitem.str.length]; 
     2533                        af.itemRValue[] = pitem.str; 
     2534                        // Get params. 
     2535                        ParamResult pr; 
     2536                        pr = nextParenItemStart(line, pitem); 
     2537                        if(pr & ParamResult.VALID) 
     2538                        { 
     2539                            if(pitem.str.length <= ApiFuncArg.MAX_LENGTH) 
     2540                            { 
     2541                                ApiFuncArg* lastarg; 
     2542                                lastarg = cast(ApiFuncArg*)mem(ApiFuncArg.sizeof + pitem.str.length); 
     2543                                lastarg.next = null; 
     2544                                lastarg.length = pitem.str.length; 
     2545                                lastarg.data.ptr[0 .. pitem.str.length] = pitem.str; 
     2546                                af.args = lastarg; // First. 
     2547                                while(pr & ParamResult.MORE) 
    16092548                                { 
    1610                                     af.args = null; 
    1611                                     break; 
     2549                                    pr = nextParenItemNext(line, pitem); 
     2550                                    if(!(pr & ParamResult.VALID)) 
     2551                                        break; 
     2552                                    if(pitem.str.length > ApiFuncArg.MAX_LENGTH) 
     2553                                    { 
     2554                                        af.args = null; 
     2555                                        break; 
     2556                                    } 
     2557                                    ApiFuncArg* arg; 
     2558                                    arg = cast(ApiFuncArg*)mem(ApiFuncArg.sizeof + pitem.str.length); 
     2559                                    arg.next = null; 
     2560                                    arg.length = pitem.str.length; 
     2561                                    arg.data.ptr[0 .. pitem.str.length] = pitem.str; 
     2562                                    lastarg.next = arg; 
     2563                                    lastarg = arg; 
    16122564                                } 
    1613                                 ApiFuncArg* arg; 
    1614                                 arg = cast(ApiFuncArg*)mem(ApiFuncArg.sizeof + pitem.str.length); 
    1615                                 arg.next = null; 
    1616                                 arg.length = pitem.str.length; 
    1617                                 arg.data.ptr[0 .. pitem.str.length] = pitem.str; 
    1618                                 lastarg.next = arg; 
    1619                                 lastarg = arg; 
    16202565                            } 
    16212566                        } 
    1622                     } 
    1623                     api.addApiFunc(s2, af); 
    1624                 } 
    1625                 break; 
    1626              
    1627             case "var": 
    1628                 { 
    1629                     if(!curmodule.length) 
    1630                         break; 
    1631                     assert('.' == parentbuf[curmodule.length]); 
    1632                      
    1633                     char[] flagstr; 
    1634                     flagstr = nextWord(line); 
    1635                     char[] path; 
    1636                     path = nextWord(line); 
    1637                     char[] ename; 
    1638                     ename = nextWord(line); 
    1639                     ParenItem pitem; 
    1640                     nextParenItemStart(line, pitem); 
    1641                     ApiVar* av; 
    1642                     av = cast(ApiVar*)mem(ApiVar.sizeof); 
    1643                     *av = ApiVar.init; 
    1644                     av.type = ApiType.VAR; 
    1645                     av.name = cast(char[])mem(ename.length)[0 .. ename.length]; 
    1646                     av.name[] = ename; 
    1647                     s2 = curmodule; 
    1648                     if("-" != path && "." != path) 
    1649                     { 
    1650                         //av.parent = path; 
    1651                         if(curmodule.length + 1 + path.length > parentbuf.length) 
    1652                             errmodpath(); 
    1653                         parentbuf[curmodule.length + 1 .. curmodule.length + 1 + path.length] = path; 
    1654                         s2 = parentbuf[0 .. curmodule.length + 1 + path.length]; 
    1655                     } 
    1656                     av.flags = parseDApiFlags(flagstr); 
    1657                     //av.itemRValue = pitem.str.dup; 
    1658                     av.itemRValue = cast(char[])mem(pitem.str.length)[0 .. pitem.str.length]; 
    1659                     av.itemRValue[] = pitem.str; 
    1660                     api.addApiVar(s2, av); 
    1661                 } 
    1662                 break; 
    1663              
    1664             case "enum": 
    1665                 { 
    1666                     if(!curmodule.length) 
    1667                         break; 
    1668                     assert('.' == parentbuf[curmodule.length]); 
    1669                      
    1670                     char[] flagstr; 
    1671                     flagstr = nextWord(line); 
    1672                     char[] path; 
    1673                     path = nextWord(line); 
    1674                     char[] ename; 
    1675                     ename = nextWord(line); 
    1676                     ApiEnum* ae; 
    1677                     ae = cast(ApiEnum*)mem(ApiEnum.sizeof); 
    1678                     *ae = ApiEnum.init; 
    1679                     ae.type = ApiType.ENUM; 
    1680                     ae.name = cast(char[])mem(ename.length)[0 .. ename.length]; 
    1681                     ae.name[] = ename; 
    1682                     s2 = curmodule; 
    1683                     if("-" != path && "." != path) 
    1684                     { 
    1685                         //ae.parent = path; 
    1686                         if(curmodule.length + 1 + path.length > parentbuf.length) 
    1687                             errmodpath(); 
    1688                         parentbuf[curmodule.length + 1 .. curmodule.length + 1 + path.length] = path; 
    1689                         s2 = parentbuf[0 .. curmodule.length + 1 + path.length]; 
    1690                     } 
    1691                     ae.flags = parseDApiFlags(flagstr); 
    1692                     api.addApiEnum(s2, ae); 
    1693                 } 
    1694                 break; 
    1695              
    1696             case "enumval": 
    1697                 { 
    1698                     if(!curmodule.length) 
    1699                         break; 
    1700                     assert('.' == parentbuf[curmodule.length]); 
    1701                      
    1702                     char[] flagstr; 
    1703                     flagstr = nextWord(line); 
    1704                     char[] path; 
    1705                     path = nextWord(line); 
    1706                     char[] ename; 
    1707                     ename = nextWord(line); 
    1708                     ApiEnumValue* ae; 
    1709                     ae = cast(ApiEnumValue*)mem(ApiEnumValue.sizeof); 
    1710                     *ae = ApiEnumValue.init; 
    1711                     ae.type = ApiType.ENUMVALUE; 
    1712                     ae.name = cast(char[])mem(ename.length)[0 .. ename.length]; 
    1713                     ae.name[] = ename; 
    1714                     s2 = curmodule; 
    1715                     if("-" != path && "." != path) 
    1716                     { 
    1717                         //ae.parent = path; 
    1718                         if(curmodule.length + 1 + path.length > parentbuf.length) 
    1719                             errmodpath(); 
    1720                         parentbuf[curmodule.length + 1 .. curmodule.length + 1 + path.length] = path; 
    1721                         s2 = parentbuf[0 .. curmodule.length + 1 + path.length]; 
    1722                     } 
    1723                     ae.flags = parseDApiFlags(flagstr); 
    1724                     api.addApiEnumValue(s2, ae); 
    1725                 } 
    1726                 break; 
    1727              
    1728             case "import": 
    1729                 { 
    1730                     if(!curmodule.length) 
    1731                         break; 
    1732                     assert('.' == parentbuf[curmodule.length]); // ? 
    1733                      
    1734                     char[] flagstr; 
    1735                     flagstr = nextWord(line); 
    1736                     char[] impmod; 
    1737                     impmod = nextWord(line); 
    1738                     ApiImport* ai; 
    1739                     ai = cast(ApiImport*)mem(ApiImport.sizeof); 
    1740                     *ai = ApiImport.init; 
    1741                     ai.type = ApiType.IMPORT; 
    1742                     ai.name = ""; // ... it doesn't have a name unless it imported-as or something. Guess that's a to-do. The = name could be the next word. 
    1743                     ai.importmodule = cast(char[])mem(impmod.length)[0 .. impmod.length]; 
    1744                     s2 = curmodule; 
    1745                     ai.flags = parseDApiFlags(flagstr); 
    1746                     api.addApiImport(s2, ai); 
    1747                 } 
    1748                 break; 
    1749              
    1750             default: ; 
    1751         } 
    1752     } 
    1753      
    1754     if(addGlobal) 
    1755         addGlobalApiInfo(api); 
    1756     return api; 
     2567                        api.addApiFunc(s2, af); 
     2568                    } 
     2569                    break; 
     2570                 
     2571                case "var": 
     2572                    { 
     2573                        if(!curscope.length) 
     2574                            break; 
     2575                        assert('.' == parentbuf[curscope.length]); 
     2576                         
     2577                        char[] flagstr; 
     2578                        flagstr = nextWord(line); 
     2579                        char[] path; 
     2580                        path = nextWord(line); 
     2581                        char[] ename; 
     2582                        ename = nextWord(line); 
     2583                        ParenItem pitem; 
     2584                        nextParenItemStart(line, pitem); 
     2585                        ApiVar* av; 
     2586                        av = cast(ApiVar*)mem(ApiVar.sizeof); 
     2587                        *av = ApiVar.init; 
     2588                        av.type = ApiType.VAR; 
     2589                        av.name = cast(char[])mem(ename.length)[0 .. ename.length]; 
     2590                        av.name[] = ename; 
     2591                        s2 = curscope; 
     2592                        if("-" != path && "." != path) 
     2593                        { 
     2594                            //av.parent = path; 
     2595                            if(curscope.length + 1 + path.length > parentbuf.length) 
     2596                                errmodpath(); 
     2597                            parentbuf[curscope.length + 1 .. curscope.length + 1 + path.length] = path; 
     2598                            s2 = parentbuf[0 .. curscope.length + 1 + path.length]; 
     2599                        } 
     2600                        av.flags = parseDApiFlags(flagstr); 
     2601                        //av.itemRValue = pitem.str.dup; 
     2602                        av.itemRValue = cast(char[])mem(pitem.str.length)[0 .. pitem.str.length]; 
     2603                        av.itemRValue[] = pitem.str; 
     2604                        api.addApiVar(s2, av); 
     2605                    } 
     2606                    break; 
     2607                 
     2608                case "enum": 
     2609                    { 
     2610                        if(!curscope.length) 
     2611                            break; 
     2612                        assert('.' == parentbuf[curscope.length]); 
     2613                         
     2614                        char[] flagstr; 
     2615                        flagstr = nextWord(line); 
     2616                        char[] path; 
     2617                        path = nextWord(line); 
     2618                        char[] ename; 
     2619                        ename = nextWord(line); 
     2620                        ApiEnum* ae; 
     2621                        ae = cast(ApiEnum*)mem(ApiEnum.sizeof); 
     2622                        *ae = ApiEnum.init; 
     2623                        ae.type = ApiType.ENUM; 
     2624                        ae.name = cast(char[])mem(ename.length)[0 .. ename.length]; 
     2625                        ae.name[] = ename; 
     2626                        s2 = curscope; 
     2627                        if("-" != path && "." != path) 
     2628                        { 
     2629                            //ae.parent = path; 
     2630                            if(curscope.length + 1 + path.length > parentbuf.length) 
     2631                                errmodpath(); 
     2632                            parentbuf[curscope.length + 1 .. curscope.length + 1 + path.length] = path; 
     2633                            s2 = parentbuf[0 .. curscope.length + 1 + path.length]; 
     2634                        } 
     2635                        ae.flags = parseDApiFlags(flagstr); 
     2636                        api.addApiEnum(s2, ae); 
     2637                    } 
     2638                    break; 
     2639                 
     2640                case "enumval": 
     2641                    { 
     2642                        if(!curscope.length) 
     2643                            break; 
     2644                        assert('.' == parentbuf[curscope.length]); 
     2645                         
     2646                        char[] flagstr; 
     2647                        flagstr = nextWord(line); 
     2648                        char[] path; 
     2649                        path = nextWord(line); 
     2650                        char[] ename; 
     2651                        ename = nextWord(line); 
     2652                        ApiEnumValue* ae; 
     2653                        ae = cast(ApiEnumValue*)mem(ApiEnumValue.sizeof); 
     2654                        *ae = ApiEnumValue.init; 
     2655                        ae.type = ApiType.ENUMVALUE; 
     2656                        ae.name = cast(char[])mem(ename.length)[0 .. ename.length]; 
     2657                        ae.name[] = ename; 
     2658                        s2 = curscope; 
     2659                        if("-" != path && "." != path) 
     2660                        { 
     2661                            //ae.parent = path; 
     2662                            if(curscope.length + 1 + path.length > parentbuf.length) 
     2663                                errmodpath(); 
     2664                            parentbuf[curscope.length + 1 .. curscope.length + 1 + path.length] = path; 
     2665                            s2 = parentbuf[0 .. curscope.length + 1 + path.length]; 
     2666                        } 
     2667                        ae.flags = parseDApiFlags(flagstr); 
     2668                        api.addApiEnumValue(s2, ae); 
     2669                    } 
     2670                    break; 
     2671                 
     2672                case "import": 
     2673                    { 
     2674                        if(!curscope.length) 
     2675                            break; 
     2676                        assert('.' == parentbuf[curscope.length]); // ? 
     2677                         
     2678                        char[] flagstr; 
     2679                        flagstr = nextWord(line); 
     2680                        char[] impmod; 
     2681                        impmod = nextWord(line); 
     2682                        ApiImport* ai; 
     2683                        ai = cast(ApiImport*)mem(ApiImport.sizeof); 
     2684                        *ai = ApiImport.init; 
     2685                        ai.type = ApiType.IMPORT; 
     2686                        ai.name = ""; // ... it doesn't have a name unless it imported-as or something. Guess that's a to-do. The = name could be the next word. 
     2687                        ai.importmodule = cast(char[])mem(impmod.length)[0 .. impmod.length]; 
     2688                        s2 = curscope; 
     2689                        ai.flags = parseDApiFlags(flagstr); 
     2690                        api.addApiImport(s2, ai); 
     2691                    } 
     2692                    break; 
     2693                 
     2694                default: ; 
     2695            } 
     2696        } 
     2697    } 
     2698     
    17572699} 
    17582700 
     
    19392881    DEPRECATED = 0x20, // d 
    19402882    PACKAGE = 0x40, // k 
     2883     
     2884    PRIVATE = 0x80, // 
     2885     
     2886    UNDOCUMENTED = 0x100, // JSON only. 
    19412887} 
    19422888 
  • trunk/win32/entice/apisearchopts.d

    r101 r102  
    4848        checkBox1.text = "Use &wildcards"; 
    4949        checkBox1.checkState = dfl.button.CheckState.CHECKED; 
    50         checkBox1.bounds = dfl.base.Rect(8, 8, 115, 15); 
     50        checkBox1.bounds = dfl.all.Rect(8, 8, 115, 15); 
    5151        checkBox1.parent = this; 
    5252        //~DFL dfl.button.CheckBox=checkBox2 
     
    5555        checkBox2.text = "Search &class names"; 
    5656        checkBox2.checkState = dfl.button.CheckState.CHECKED; 
    57         checkBox2.bounds = dfl.base.Rect(8, 40, 139, 15); 
     57        checkBox2.bounds = dfl.all.Rect(8, 40, 139, 15); 
    5858        checkBox2.parent = this; 
    5959        //~DFL dfl.button.CheckBox=checkBox3 
     
    6262        checkBox3.text = "Search &struct names"; 
    6363        checkBox3.checkState = dfl.button.CheckState.CHECKED; 
    64         checkBox3.bounds = dfl.base.Rect(8, 64, 139, 15); 
     64        checkBox3.bounds = dfl.all.Rect(8, 64, 139, 15); 
    6565        checkBox3.parent = this; 
    6666        //~DFL dfl.button.CheckBox=checkBox4 
     
    6969        checkBox4.text = "Search &interface names"; 
    7070        checkBox4.checkState = dfl.button.CheckState.CHECKED; 
    71         checkBox4.bounds = dfl.base.Rect(8, 88, 139, 15); 
     71        checkBox4.bounds = dfl.all.Rect(8, 88, 139, 15); 
    7272        checkBox4.parent = this; 
    7373        //~DFL dfl.button.CheckBox=checkBox5 
     
    7676        checkBox5.text = "Search &union names"; 
    7777        checkBox5.checkState = dfl.button.CheckState.CHECKED; 
    78         checkBox5.bounds = dfl.base.Rect(8, 112, 139, 15); 
     78        checkBox5.bounds = dfl.all.Rect(8, 112, 139, 15); 
    7979        checkBox5.parent = this; 
    8080        //~DFL dfl.button.CheckBox=checkBox6 
     
    8383        checkBox6.text = "Search &function names (top level / global)"; 
    8484        checkBox6.checkState = dfl.button.CheckState.CHECKED; 
    85         checkBox6.bounds = dfl.base.Rect(8, 144, 251, 15); 
     85        checkBox6.bounds = dfl.all.Rect(8, 144, 251, 15); 
    8686        checkBox6.parent = this; 
    8787        //~DFL dfl.button.CheckBox=checkBox7 
     
    9090        checkBox7.text = "Search &method / member function names"; 
    9191        checkBox7.checkState = dfl.button.CheckState.CHECKED; 
    92         checkBox7.bounds = dfl.base.Rect(8, 168, 251, 15); 
     92        checkBox7.bounds = dfl.all.Rect(8, 168, 251, 15); 
    9393        checkBox7.parent = this; 
    9494        //~DFL dfl.button.CheckBox=checkBox8 
     
    9696        checkBox8.name = "checkBox8"; 
    9797        checkBox8.text = "Search &constant names"; 
    98         checkBox8.bounds = dfl.base.Rect(8, 200, 219, 15); 
     98        checkBox8.bounds = dfl.all.Rect(8, 200, 219, 15); 
    9999        checkBox8.parent = this; 
    100100        //~DFL dfl.button.CheckBox=checkBox9 
     
    102102        checkBox9.name = "checkBox9"; 
    103103        checkBox9.text = "Search &field / member variable names"; 
    104         checkBox9.bounds = dfl.base.Rect(8, 224, 219, 15); 
     104        checkBox9.bounds = dfl.all.Rect(8, 224, 219, 15); 
    105105        checkBox9.parent = this; 
    106106        //~DFL dfl.button.CheckBox=checkBox10 
     
    108108        checkBox10.name = "checkBox10"; 
    109109        checkBox10.text = "Search pu&blic items"; 
    110         checkBox10.bounds = dfl.base.Rect(8, 256, 155, 15); 
     110        checkBox10.bounds = dfl.all.Rect(8, 256, 155, 15); 
    111111        checkBox10.parent = this; 
    112112        //~DFL dfl.button.CheckBox=checkBox11 
     
    114114        checkBox11.name = "checkBox11"; 
    115115        checkBox11.text = "Search p&rotected items"; 
    116         checkBox11.bounds = dfl.base.Rect(8, 280, 155, 15); 
     116        checkBox11.bounds = dfl.all.Rect(8, 280, 155, 15); 
    117117        checkBox11.parent = this; 
    118118        //~DFL dfl.button.CheckBox=checkBox12 
     
    120120        checkBox12.name = "checkBox12"; 
    121121        checkBox12.text = "Treat properties as fields"; 
    122         checkBox12.bounds = dfl.base.Rect(8, 312, 155, 15); 
     122        checkBox12.bounds = dfl.all.Rect(8, 312, 155, 15); 
    123123        checkBox12.parent = this; 
    124124        //~Entice Designer 0.7.3pre4 code ends here. 
  • trunk/win32/entice/apiviewer.d

    r101 r102  
    55import std.uri, std.string; 
    66 
    7 private import dfl.all, dfl.winapi
    8  
    9 import dscale
     7private import dfl.all
     8 
     9import dscale, util
    1010 
    1111import resource; 
    1212 
    1313import apiinfo; 
    14  
    15  
    16 void launchUrl(char[] url) 
    17 { 
    18     if(cast(int)ShellExecuteA(null, "open", std.string.toStringz(url), null, null, 0) <= 32) 
    19     { 
    20         msgBox("Unable to open URL"); 
    21     } 
    22      
    23     /+ 
    24     ShellExecuteA(null, "open", "rundll32.exe", 
    25         std.string.toStringz("url.dll,FileProtocolHandler " ~ url), 
    26         null, SW_SHOWDEFAULT); 
    27     +/ 
    28 } 
    2914 
    3015 
     
    222207    void dispApi(ApiFlags af, char[] apicat, char[] beforename, char[] name, char[] aftername = null) 
    223208    { 
     209        char[] s; 
     210        if(af & ApiFlags.PRIVATE) 
     211        { 
     212            s ~= "private "; 
     213        } 
     214        else if(af & ApiFlags.PROTECTED) 
     215        { 
     216            s ~= "protected "; 
     217        } 
     218        else if(af & ApiFlags.PACKAGE) 
     219        { 
     220            s ~= "package "; 
     221        } 
     222        if(af & ApiFlags.STATIC) 
     223        { 
     224            s ~= "static "; 
     225        } 
     226        else if(af & ApiFlags.FINAL) 
     227        { 
     228            s ~= "final "; 
     229        } 
     230        if(s.length) 
     231        { 
     232            infoDisp.selectionColor = Color(0x7F, 0, 0).blendColor(infoDisp.foreColor); 
     233            infoDisp.appendText(s); 
     234        } 
     235         
    224236        infoDisp.selectionColor = Color(0, 0, 0xFF).blendColor(infoDisp.foreColor); 
    225237        infoDisp.appendText(apicat ~ " "); 
    226          
    227         char[] s; 
    228         if(af & ApiFlags.PROTECTED) 
    229         { 
    230             s ~= "protected "; 
    231         } 
    232         if(af & ApiFlags.STATIC) 
    233         { 
    234             s ~= "static "; 
    235         } 
    236         if(s.length) 
    237         { 
    238             infoDisp.selectionColor = Color(0x7F, 0, 0).blendColor(infoDisp.foreColor); 
    239             infoDisp.appendText(s); 
    240         } 
    241238         
    242239        if(beforename.length) 
     
    310307                        else 
    311308                        { 
    312                             if(af.functype & ApiFunc.METHOD) 
     309                            if(af.entry.name == "this") 
     310                            { 
     311                                dispApi(apinode.apiEntry.flags, "constructor", af.itemRValue ~ " ", apinode.apiEntry.name, af.getArgsString()); 
     312                            } 
     313                            else if(af.entry.name == "~this") 
     314                            { 
     315                                dispApi(apinode.apiEntry.flags, "destructor", af.itemRValue ~ " ", apinode.apiEntry.name, af.getArgsString()); 
     316                            } 
     317                            else if(af.functype & ApiFunc.METHOD) 
    313318                            { 
    314319                                dispApi(apinode.apiEntry.flags, "method", af.itemRValue ~ " ", apinode.apiEntry.name, af.getArgsString()); 
  • trunk/win32/entice/checkup.d

    r101 r102  
    55private import std.socket, std.string; 
    66 
    7 private import dfl.all, dfl.winapi; 
     7private import dfl.all, dfl.internal.winapi; 
    88 
    99private import dfldesigner; 
     
    451451        checkout.multiline = true; 
    452452        checkout.readOnly = true; 
    453         checkout.bounds = dfl.base.Rect(8, 8, 248, 104); 
     453        checkout.bounds = dfl.all.Rect(8, 8, 248, 104); 
    454454        checkout.parent = this; 
    455455        //~DFL dfl.button.Button=checkBtn 
     
    457457        checkBtn.name = "checkBtn"; 
    458458        checkBtn.text = "Check"; 
    459         checkBtn.bounds = dfl.base.Rect(104, 120, 75, 23); 
     459        checkBtn.bounds = dfl.all.Rect(104, 120, 75, 23); 
    460460        checkBtn.parent = this; 
    461461        //~DFL dfl.button.Button=closeBtn 
     
    463463        closeBtn.name = "closeBtn"; 
    464464        closeBtn.text = "Close"; 
    465         closeBtn.bounds = dfl.base.Rect(184, 120, 75, 23); 
     465        closeBtn.bounds = dfl.all.Rect(184, 120, 75, 23); 
    466466        closeBtn.parent = this; 
    467467        //~Entice Designer 0.8pre8 code ends here. 
  • trunk/win32/entice/controlchildren.d

    r101 r102  
    33 
    44 
    5 private import dfl.all, dfl.winapi; 
     5private import dfl.all, dfl.internal.winapi; 
    66 
    77private import design, designcontrol, designform; 
  • trunk/win32/entice/ddcontrolchildren.d

    r101 r102  
    115115 
    116116 
    117 void updateVariableNames(DflDesignTab dtab, EditorTab etab
     117void updateVariableNames(DflDesignTab dtab, EditorTab etab, bool alsoDesignSource = true
    118118{ 
    119119    assert(dtab.entity !is null); 
     
    154154    } 
    155155     
     156    etab.sci.beginDesignUpdate(); 
     157     
    156158    etab.sci.sendEditor(SCI_REPLACETARGET, dvarsec.length, cast(LPARAM)dvarsec.ptr); 
    157     etab.sci.changedDesignerVariables(); // Clears undo buffer if needed. 
    158 
    159  
    160  
    161 void updateVariableNames(DflDesignTab dtab) 
     159    etab.sci.changedDesignerVariables(); 
     160     
     161    if(alsoDesignSource) 
     162    { 
     163        _regenDesignSource(dtab, etab); 
     164    } 
     165     
     166    etab.sci.endDesignUpdate(); 
     167
     168 
     169 
     170void updateVariableNames(DflDesignTab dtab, bool alsoDesignSource = true) 
    162171{ 
    163172    EditorTab etab; 
     
    171180    } 
    172181     
    173     updateVariableNames(dtab, etab); 
     182    updateVariableNames(dtab, etab, alsoDesignSource); 
    174183} 
    175184 
     
    177186// Note: does not set as modified. 
    178187void regenDesignSource(DflDesignTab dtab, EditorTab etab) 
     188{ 
     189    etab.sci.beginDesignUpdate(); 
     190    _regenDesignSource(dtab, etab); 
     191    etab.sci.endDesignUpdate(); 
     192} 
     193 
     194void regenDesignSource(DflDesignTab dtab) 
     195{ 
     196    EditorTab etab; 
     197     
     198    assert(dtab.entity !is null); 
     199    foreach(ETab ontab; dtab.entity.etabs) 
     200    { 
     201        etab = cast(EditorTab)ontab; 
     202        if(etab) 
     203            break; 
     204    } 
     205     
     206    regenDesignSource(dtab, etab); 
     207} 
     208 
     209private void _regenDesignSource(DflDesignTab dtab, EditorTab etab) 
    179210{ 
    180211    assert(dtab.entity !is null); 
     
    225256        etab.sci.foldDesignerSource(); 
    226257    } 
    227 } 
    228  
    229  
    230 void regenDesignSource(DflDesignTab dtab) 
    231 { 
    232     EditorTab etab; 
    233      
    234     assert(dtab.entity !is null); 
    235     foreach(ETab ontab; dtab.entity.etabs) 
    236     { 
    237         etab = cast(EditorTab)ontab; 
    238         if(etab) 
    239             break; 
    240     } 
    241      
    242     regenDesignSource(dtab, etab); 
    243258} 
    244259 
     
    422437    { 
    423438        Size sz; 
    424         sz = typeof(this).defaultSize; 
     439        //sz = typeof(this).defaultSize; // DMD 1.033: ddcontrolchildren.d(424): Error: this for defaultSize needs to be type Form not type ddcontrolchildren.DesignUnknownControl 
     440        sz = defaultSize; 
    425441        if(!sz.width) 
    426442            sz.width = 32; 
     
    784800    private void showPropBox() 
    785801    { 
    786         // Show my prop box first. Showing it after causes extra flickering. 
    787         //propBox.dock = DockStyle.FILL; 
    788         propBox.parent = propPanel; 
    789         propBox.visible = true; 
     802        // If multiple selected, don't show any (for now). 
     803        // Later I'll show the properties in common. 
     804        if(!dControlMultipleSelected(this, true)) 
     805        { 
     806            // Show my prop box first. Showing it after causes extra flickering. 
     807            //propBox.dock = DockStyle.FILL; 
     808            propBox.parent = propPanel; 
     809            propBox.visible = true; 
     810        } 
    790811         
    791812        // Hide other prop boxes. 
     
    876897        final void updatePropInfo() 
    877898        { 
    878             if(propBox) 
    879             { 
    880                 updatePropInfoFromPropBox(propBox); 
     899            int numsel = dControlCountSelected(this, true); 
     900            if(numsel > 1) 
     901            { 
     902                // If multiple selected,.. 
     903                propInfo.setInfo(std.string.toString(numsel) ~ " selected", null); 
     904            } 
     905            else 
     906            { 
     907                if(propBox) 
     908                { 
     909                    updatePropInfoFromPropBox(propBox); 
     910                } 
    881911            } 
    882912        } 
     
    969999     
    9701000     
    971     void updateVariableNames(
    972     { 
    973         //if(!loaded) 
     1001    void updateVariableNames(bool alsoDesignSource = true, bool force = false
     1002    { 
     1003        //if(!force && !loaded) 
    9741004        //  return; 
    9751005         
    976         .updateVariableNames(dtab); 
     1006        if(alsoDesignSource) 
     1007        { 
     1008            if(!force && !loaded) 
     1009                alsoDesignSource = false; 
     1010        } 
     1011         
     1012        .updateVariableNames(dtab, alsoDesignSource); 
    9771013    } 
    9781014     
     
    10031039            updateVariableNames(); 
    10041040        } 
    1005          
    1006         regenDesignSource(); 
     1041        else 
     1042        { 
     1043            regenDesignSource(); 
     1044        } 
    10071045         
    10081046        // Sometimes a prop change causes a visual update, so need to refresh design overlays. 
     
    11101148        dtab.entity.modified = true; 
    11111149         
     1150        loaded = true; 
     1151         
    11121152        updateVariableNames(); 
    1113          
    1114         loaded = true; 
    1115          
    1116         regenDesignSource(); 
    11171153    } 
    11181154     
    11191155     
    11201156    void initRemoveThisDesign(bit first) 
    1121     in 
    11221157    { 
    11231158        assert(this.dtab !is null); 
    1124     } 
    1125     body 
    1126     { 
     1159         
    11271160        Control ctrl; 
    11281161        IDesignControl dcparent; 
     
    11631196         
    11641197        dtab.entity.modified = true; 
    1165         updateVariableNames(); 
    1166         regenDesignSource(true); // Has to be forced because the control is gone! 
     1198        updateVariableNames(true, true); // Design update to be forced because the control is gone! 
    11671199    } 
    11681200     
     
    11941226    // Adding -dctrl- to DflDesignTab dtab. -dctrl-'s icon is -icon-. 
    11951227    final void addDesignControl(IDflDesignChildControl dctrl, DflDesignTab dtab, Icon icon) 
    1196     in 
    11971228    { 
    11981229        assert(dctrl !is null); 
    11991230        //assert(pcombo !is null); 
    12001231        assert(dtab !is null); 
    1201     } 
    1202     body 
    1203     { 
     1232         
    12041233        ctrlSpacing = false; 
    12051234         
     
    12561285     
    12571286    final void removeDesignControl(IDflDesignChildControl dctrl, bit first = true) 
    1258     in 
    12591287    { 
    12601288        assert(dctrl !is null); 
    1261     } 
    1262     body 
    1263     { 
     1289         
    12641290        dctrl.initRemoveThisDesign(first); 
    12651291    } 
     
    12751301     
    12761302     
    1277     protected void deleteThisDesign() 
    1278     { 
     1303    protected void deleteAllSelectedDesign() 
     1304    { 
     1305        IDflDesignChildControl[4] _delbuf; 
     1306        IDflDesignChildControl[] delbuf = _delbuf; 
     1307        int numdels = 0; 
     1308         
    12791309        dControlAllSelected(this, 
    1280             delegate bit(IDesignControlItem dctrli) 
     1310            delegate (IDesignControlItem dctrli) 
    12811311            { 
    12821312                IDflDesignChildControl dctrlc; 
    12831313                dctrlc = cast(IDflDesignChildControl)dctrli; 
    1284                 if(dctrlc && !(dctrlc.getDesignControlFlags() & DdDesignControlFlags.OPEN_ITEM)
     1314                if(dctrlc
    12851315                { 
    1286                     removeDesignControl(dctrlc); 
     1316                    if(numdels >= delbuf.length) 
     1317                        delbuf ~= dctrlc; 
     1318                    else 
     1319                        delbuf[numdels] = dctrlc; 
     1320                    numdels++; 
    12871321                } 
    12881322                else 
     
    12921326                return true; // Continue. 
    12931327            }); 
     1328         
     1329        foreach(IDflDesignChildControl dctrlc; delbuf[0 .. numdels]) 
     1330        { 
     1331            if(!(dctrlc.getDesignControlFlags() & DdDesignControlFlags.OPEN_ITEM)) 
     1332            { 
     1333                removeDesignControl(dctrlc); 
     1334            } 
     1335        } 
     1336         
    12941337    } 
    12951338     
     
    12981341    void itemDeleteKey() 
    12991342    { 
    1300         //if(!(ddcflags & DdDesignControlFlags.OPEN_ITEM)) 
    1301             deleteThisDesign(); 
     1343        deleteAllSelectedDesign(); 
    13021344    } 
    13031345     
     
    13291371                 
    13301372                doneUsingTool(); 
    1331             } 
     1373                 
     1374                return; // Handled! 
     1375            } 
     1376        } 
     1377         
     1378        version(ENTICE_MULTISEL) 
     1379        { 
     1380            // Select all in selection rectangle. 
     1381            bool clearOthers = true; 
     1382            this.getItems( 
     1383                (IDesignControlItem idci) 
     1384                { 
     1385                    Rect idciRect; 
     1386                    idci.getItemBounds(idciRect); 
     1387                    if(itembounds.intersectsWith(idciRect)) 
     1388                    { 
     1389                        IDesignControl idc = cast(IDesignControl)idci; 
     1390                        if(idc) 
     1391                        { 
     1392                            dControlUpdateSelect(idc, true, clearOthers); 
     1393                            clearOthers = false; 
     1394                        } 
     1395                    } 
     1396                    return true; // Continue. 
     1397                }); 
    13321398        } 
    13331399    } 
     
    13641430                 
    13651431                doneUsingTool(); 
     1432                 
     1433                return; // Handled! 
    13661434            } 
    13671435        } 
     
    13731441    void itemPaint(PAINTSTRUCT* ps) 
    13741442    { 
    1375         auto Graphics g = new Graphics(ps.hdc, false); 
     1443        scope Graphics g = new Graphics(ps.hdc, false); 
    13761444        auto PaintEventArgs ea = new PaintEventArgs(g, Rect(&ps.rcPaint)); 
    13771445        onPaint(ea); 
     
    15221590                if(mod) 
    15231591                { 
    1524                     regenDesignSource(); 
    15251592                    if(modvars) 
    15261593                        updateVariableNames(); 
     1594                    else 
     1595                        regenDesignSource(); 
    15271596                     
    15281597                    if(newtype) 
     
    15841653        if(topmost) 
    15851654        { 
    1586             scope zof = new ZOF.ZOrderForm(); 
     1655            auto zof = new ZOF.ZOrderForm(); 
    15871656             
    15881657            void allchildren(Control cc, uint indentlevel) 
     
    16651734    private void deleteMenu_click(Object sender, EventArgs ea) 
    16661735    { 
    1667         deleteThisDesign(); 
     1736        deleteAllSelectedDesign(); 
    16681737         
    16691738        dtab.entity.modified = true; 
     
    17541823     
    17551824    void initContextMenu() 
    1756     in 
     1825    /+in 
    17571826    { 
    17581827        assert(cmenu is null); 
     
    17621831        assert(cmenu !is null); 
    17631832    } 
    1764     body 
     1833    body+/ 
    17651834    { 
    17661835        MenuItem mi; 
     
    22172286                    delegate(HDC hdc, Rect r) 
    22182287                    { 
    2219                         auto Graphics g = new Graphics(hdc, false); 
    2220                         auto PaintEventArgs ea = new PaintEventArgs(g, r); 
     2288                        scope Graphics g = new Graphics(hdc, false); 
     2289                        scope PaintEventArgs ea = new PaintEventArgs(g, r); 
    22212290                        onPaintBackground(ea); 
    22222291                    }, 
     
    69677036 
    69687037 
    6969 private extern(Windows) void childEditWndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 
     7038private extern(Windows) LRESULT childEditWndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 
    69707039{ 
    69717040    Message m; 
  • trunk/win32/entice/ddcontrolspace.d

    r101 r102  
    33 
    44 
    5 import dfl.all, dfl.winapi; 
     5import dfl.all, dfl.internal.winapi; 
    66 
    77import winapi, design; 
  • trunk/win32/entice/dddesignform.d

    r101 r102  
    1515 
    1616const char[][] FORM_START_POSITION_NAMES = ["CENTER_PARENT", "CENTER_SCREEN", "MANUAL", 
    17     "WINDOWS_DEFAULT_BOUNDS", "WINDOWS_DEFAULT_LOCATION"]; 
     17    "DEFAULT_BOUNDS", "DEFAULT_LOCATION"]; 
    1818 
    1919const char[][] FORM_WINDOW_STATE_NAMES = ["MAXIMIZED", "MINIMIZED", "NORMAL"]; 
  • trunk/win32/entice/ddeditorstyler.d

    r101 r102  
    44 
    55private import std.string; 
    6 private import dfl.all, dfl.winapi; 
     6private import dfl.all, dfl.internal.winapi; 
    77private import editorstyler, scistyles, util; 
    88private import dfldesigner; 
  • trunk/win32/entice/ddexprops.d

    r101 r102  
    33 
    44 
    5 private import dfl.all, dfl.winapi; 
     5private import dfl.all, dfl.internal.winapi; 
    66 
    77import design; 
     
    135135        itemNameDisp.text = "Foo"; 
    136136        itemNameDisp.textAlign = dfl.base.ContentAlignment.MIDDLE_LEFT; 
    137         itemNameDisp.bounds = dfl.base.Rect(36, 7, 276, 23); 
     137        itemNameDisp.bounds = dfl.all.Rect(36, 7, 276, 23); 
    138138        itemNameDisp.parent = this; 
    139139        //~DFL dfl.picturebox.PictureBox=picBox 
     
    141141        picBox.name = "picBox"; 
    142142        picBox.sizeMode = dfl.picturebox.PictureBoxSizeMode.CENTER_IMAGE; 
    143         picBox.bounds = dfl.base.Rect(8, 8, 23, 23); 
     143        picBox.bounds = dfl.all.Rect(8, 8, 23, 23); 
    144144        picBox.parent = this; 
    145145        //~DFL dfl.label.Label=label1 
     
    148148        label1.text = "&Type:"; 
    149149        label1.textAlign = dfl.base.ContentAlignment.MIDDLE_LEFT; 
    150         label1.bounds = dfl.base.Rect(8, 40, 76, 23); 
     150        label1.bounds = dfl.all.Rect(8, 40, 76, 23); 
    151151        label1.parent = this; 
    152152        //~DFL dfl.textbox.TextBox=typeBox 
    153153        typeBox = new dfl.textbox.TextBox(); 
    154154        typeBox.name = "typeBox"; 
    155         typeBox.bounds = dfl.base.Rect(112, 40, 192, 23); 
     155        typeBox.bounds = dfl.all.Rect(112, 40, 192, 23); 
    156156        typeBox.parent = this; 
    157157        //~DFL dfl.label.Label=ctorLabel 
     
    160160        ctorLabel.text = "&Constructor call:"; 
    161161        ctorLabel.textAlign = dfl.base.ContentAlignment.MIDDLE_LEFT; 
    162         ctorLabel.bounds = dfl.base.Rect(8, 72, 92, 23); 
     162        ctorLabel.bounds = dfl.all.Rect(8, 72, 92, 23); 
    163163        ctorLabel.parent = this; 
    164164        //~DFL dfl.textbox.TextBox=ctorBox 
     
    166166        ctorBox.name = "ctorBox"; 
    167167        ctorBox.text = "()"; 
    168         ctorBox.bounds = dfl.base.Rect(112, 72, 192, 23); 
     168        ctorBox.bounds = dfl.all.Rect(112, 72, 192, 23); 
    169169        ctorBox.parent = this; 
    170170        //~DFL dfl.button.CheckBox=autoScaleCheck 
     
    173173        autoScaleCheck.enabled = false; 
    174174        autoScaleCheck.text = "autoScale"; 
    175         autoScaleCheck.bounds = dfl.base.Rect(8, 104, 107, 23); 
     175        autoScaleCheck.bounds = dfl.all.Rect(8, 104, 107, 23); 
    176176        autoScaleCheck.parent = this; 
    177177        //~DFL dfl.button.Button=okBtn 
     
    179179        okBtn.name = "okBtn"; 
    180180        okBtn.text = "OK"; 
    181         okBtn.bounds = dfl.base.Rect(152, 104, 75, 23); 
     181        okBtn.bounds = dfl.all.Rect(152, 104, 75, 23); 
    182182        okBtn.parent = this; 
    183183        //~DFL dfl.button.Button=cancelBtn 
     
    185185        cancelBtn.name = "cancelBtn"; 
    186186        cancelBtn.text = "Cancel"; 
    187         cancelBtn.bounds = dfl.base.Rect(232, 104, 75, 23); 
     187        cancelBtn.bounds = dfl.all.Rect(232, 104, 75, 23); 
    188188        cancelBtn.parent = this; 
    189189        //~Entice Designer 0.8pre8 code ends here. 
  • trunk/win32/entice/ddfindreplace.d

    r101 r102  
    88 
    99private import std.string, std.utf, std.ctype; 
    10 private import dfl.all, dfl.winapi; 
     10private import dfl.all, dfl.internal.winapi; 
    1111private import dfl.scintilla, dfl.cpp.scintilla, dfl.cpp.scilexer; 
    1212private import findreplace, dfldesigner; 
     
    2020    //import std.regexp; 
    2121    import myregexp; 
     22} 
     23 
     24 
     25interface IFindReplaceTitle 
     26{ 
     27    string findReplaceTitle(); // getter 
    2228} 
    2329 
     
    164170        if(!findrep) 
    165171            return; 
     172         
     173        { 
     174            IFindReplaceTitle ifrt = cast(IFindReplaceTitle)sci; 
     175            if(ifrt) 
     176            { 
     177                findrep.text = ifrt.findReplaceTitle(); 
     178            } 
     179            else 
     180            { 
     181                if(allowreplace && sci) 
     182                    findrep.text = "Find and Replace"; 
     183                else 
     184                    findrep.text = "Find"; 
     185            } 
     186        } 
     187         
    166188        //allowreplace = !(sci && sci.sendEditor(SCI_GETREADONLY)); 
    167189        allowreplace = !(!sci || sci.sendEditor(SCI_GETREADONLY)); 
     
    206228     
    207229    static private void _createFindrep() 
    208     in 
    209230    { 
    210231        assert(findrep is null); 
    211     } 
    212     body 
    213     { 
     232         
    214233        with(mainForm) 
    215234        { 
     
    378397        { 
    379398            void doReplaceAtI() 
    380             in 
    381399            { 
    382400                assert(-1 != i); 
    383             } 
    384             body 
    385             { 
     401                 
    386402                if(regexCheck.checked) 
    387403                { 
     
    522538    // if wrap is true, when hitting iend, wraps back to 0 to istart. 
    523539    void findrepReplaceHere(uint istart, uint iend, uint maxreplacements = 1, bool wrap = false) 
    524     in 
    525540    { 
    526541        assert(findrep !is null); 
    527542        assert(istart <= iend); 
    528     } 
    529     body 
    530     { 
     543         
    531544        assert(allowreplace); 
    532545         
     
    605618         
    606619        void doReplaceAtI() 
    607         in 
    608620        { 
    609621            assert(-1 != i); 
    610         } 
    611         body 
    612         { 
     622             
    613623            flen = sci.sendEditor(SCI_GETTARGETEND) - sci.sendEditor(SCI_GETTARGETSTART); 
    614624             
     
    12001210    // -findString- must be set. 
    12011211    static void doFindNext() 
    1202     in 
    12031212    { 
    12041213        assert(findString.length); 
    1205     } 
    1206     body 
    1207     { 
     1214         
    12081215        if(!findrep) 
    12091216            _createFindrep(); 
     
    12811288    // -findString- must be set. 
    12821289    static void doFindPrevious() 
    1283     in 
    12841290    { 
    12851291        assert(findString.length); 
    1286     } 
    1287     body 
    1288     { 
     1292         
    12891293        if(!findrep) 
    12901294            _createFindrep(); 
  • trunk/win32/entice/ddopenparser.d

    r101 r102  
    66    std.intrinsic, std.utf, std.stdint; 
    77 
    8 private import dfl.all, dfl.winapi, dfl.utf; 
     8private import dfl.all, dfl.internal.winapi, dfl.internal.utf; 
    99private import dfl.scintilla, dfl.cpp.scintilla, dfl.cpp.scilexer; 
    1010 
  • trunk/win32/entice/ddoptions.d

    r101 r102  
    1414 
    1515import ddoptsdesignpanel, ddoptsgeneralpanel, ddoptseditorpanel, 
    16     ddoptsnetworkpanel, ddoptspluginspanel, ddoptsfiletypespanel; 
     16    ddoptsnetworkpanel, ddoptspluginspanel, ddoptsfiletypespanel, 
     17    ddoptscompilerpanel; 
    1718 
    1819import rgroup, rdflregistry; 
     
    675676    uint32_t tabFirstShow = 0; 
    676677     
     678    void delegate(DdOptionsForm) optionsReady = null; 
     679     
    677680     
    678681    this() 
     
    727730            addTab(new KeywordsOptTab); 
    728731            //addTab(new FileTypesOptTab); 
     732            addTab(new CompilerOptTab); 
    729733            addTab(new NetworkOptTab); 
    730734            version(QUICK_OPT) 
     
    761765            } 
    762766        } 
     767         
     768        if(optionsReady) 
     769        { 
     770            optionsReady(this); 
     771        } 
    763772    } 
    764773     
    765774     
    766775    final int findTabByGid(uint32_t gid) 
    767     in 
    768776    { 
    769777        assert(isValidGid(gid)); 
    770     } 
    771     body 
    772     { 
     778         
     779         
    773780        union _tab 
    774781        { 
     
    827834                        else 
    828835                        { 
    829                             RegistryValueDword regDword = void; 
    830                             RegistryValueSz regSz = void; 
    831                             RegistryValueBinary regBin = void; 
    832                              
    833                             //subKey.setValue(opt.optName(), regval); 
    834                             regDword = cast(RegistryValueDword)regval; 
     836                            RegistryValueDword regDword = cast(RegistryValueDword)regval; 
    835837                            if(regDword) 
    836838                            { 
     
    839841                            else 
    840842                            { 
    841                                 regSz = cast(RegistryValueSz)regval; 
     843                                RegistryValueSz regSz = cast(RegistryValueSz)regval; 
    842844                                if(regSz) 
    843845                                { 
     
    846848                                else 
    847849                                { 
    848                                     regBin = cast(RegistryValueBinary)regval; 
     850                                    RegistryValueBinary regBin = cast(RegistryValueBinary)regval; 
    849851                                    if(regBin) 
    850852                                    { 
     
    853855                                    else 
    854856                                    { 
    855                                         assert(0, "Invalid option type"); 
     857                                        RegistryValueMultiSz regSzs = cast(RegistryValueMultiSz)regval; 
     858                                        if(regSzs) 
     859                                        { 
     860                                            subKey.setEntryString(opt.optName, stringsToCsv(regSzs.value)); 
     861                                        } 
     862                                        else 
     863                                        { 
     864                                            assert(0, "Invalid option type"); 
     865                                        } 
    856866                                    } 
    857867                                } 
  • trunk/win32/entice/ddoptsdesignpanel.d

    r101 r102  
    3838        //~DFL Panel 
    3939        name = "DdOptsDesignPanel"; 
    40         bounds = dfl.base.Rect(0, 25, 400, 296); 
     40        bounds = dfl.all.Rect(0, 25, 400, 296); 
    4141        autoScaleBaseSize = Size(5, 13); 
    4242        //~DFL OptCheckBox:dfl.button.CheckBox=showGridCheck 
     
    4444        showGridCheck.name = "showGridCheck"; 
    4545        showGridCheck.text = "Show &grid lines with spacing of:"; 
    46         showGridCheck.bounds = dfl.base.Rect(8, 8, 174, 23); 
     46        showGridCheck.bounds = dfl.all.Rect(8, 8, 174, 23); 
    4747        showGridCheck.parent = this; 
    4848        //~DFL OptTextBoxDword:dfl.textbox.TextBox=gridSizeBox 
    4949        gridSizeBox = new OptTextBoxDword("gridsize",575913561,false,true); 
    5050        gridSizeBox.name = "gridSizeBox"; 
    51         gridSizeBox.bounds = dfl.base.Rect(187, 8, 32, 23); 
     51        gridSizeBox.bounds = dfl.all.Rect(187, 8, 32, 23); 
    5252        gridSizeBox.parent = this; 
    5353        //~DFL OptCheckBox:dfl.button.CheckBox=snapGridCheck 
     
    5555        snapGridCheck.name = "snapGridCheck"; 
    5656        snapGridCheck.text = "&Snap to grid"; 
    57         snapGridCheck.bounds = dfl.base.Rect(8, 32, 115, 23); 
     57        snapGridCheck.bounds = dfl.all.Rect(8, 32, 115, 23); 
    5858        snapGridCheck.parent = this; 
    5959        //~DFL OptCheckBox:dfl.button.CheckBox=sameToolCheck 
     
    6161        sameToolCheck.name = "sameToolCheck"; 
    6262        sameToolCheck.text = "Always stay on the same &tool"; 
    63         sameToolCheck.bounds = dfl.base.Rect(8, 56, 275, 23); 
     63        sameToolCheck.bounds = dfl.all.Rect(8, 56, 275, 23); 
    6464        sameToolCheck.parent = this; 
    6565        //~DFL OptCheckBox:dfl.button.CheckBox=prevSpaceCheck 
     
    6767        prevSpaceCheck.name = "prevSpaceCheck"; 
    6868        prevSpaceCheck.text = "Insert space when &hovering edges of docked controls"; 
    69         prevSpaceCheck.bounds = dfl.base.Rect(8, 80, 355, 23); 
     69        prevSpaceCheck.bounds = dfl.all.Rect(8, 80, 355, 23); 
    7070        prevSpaceCheck.parent = this; 
    7171        //~Entice Designer 0.8.2pre7 code ends here. 
  • trunk/win32/entice/ddoptsnetworkpanel.d

    r101 r102  
    3939        //~DFL Panel 
    4040        name = "DdOptsNetworkPanel"; 
    41         bounds = dfl.base.Rect(0, 25, 384, 272); 
     41        bounds = dfl.all.Rect(0, 25, 384, 272); 
    4242        autoScaleBaseSize = Size(5, 13); 
    4343        //~DFL dfl.groupbox.GroupBox=proxyGroup 
    4444        proxyGroup = new dfl.groupbox.GroupBox(); 
    4545        proxyGroup.name = "proxyGroup"; 
    46         proxyGroup.bounds = dfl.base.Rect(8, 8, 328, 60); 
     46        proxyGroup.bounds = dfl.all.Rect(8, 8, 328, 60); 
    4747        proxyGroup.parent = this; 
    4848        //~DFL OptCheckBox:dfl.button.CheckBox=useProxyCheck 
     
    5050        useProxyCheck.name = "useProxyCheck"; 
    5151        useProxyCheck.text = "Use &proxy server"; 
    52         useProxyCheck.bounds = dfl.base.Rect(10, -3, 105, 23); 
     52        useProxyCheck.bounds = dfl.all.Rect(10, -3, 105, 23); 
    5353        useProxyCheck.parent = proxyGroup; 
    5454        //~DFL dfl.label.Label=proxyHttpServerLabel 
     
    5858        proxyHttpServerLabel.text = "HTTP &server:"; 
    5959        proxyHttpServerLabel.textAlign = dfl.base.ContentAlignment.MIDDLE_LEFT; 
    60         proxyHttpServerLabel.bounds = dfl.base.Rect(12, 25, 68, 23); 
     60        proxyHttpServerLabel.bounds = dfl.all.Rect(12, 25, 68, 23); 
    6161        proxyHttpServerLabel.parent = proxyGroup; 
    6262        //~DFL OptTextBox:dfl.textbox.TextBox=proxyHttpServerBox 
     
    6464        proxyHttpServerBox.name = "proxyHttpServerBox"; 
    6565        proxyHttpServerBox.enabled = false; 
    66         proxyHttpServerBox.bounds = dfl.base.Rect(88, 25, 128, 23); 
     66        proxyHttpServerBox.bounds = dfl.all.Rect(88, 25, 128, 23); 
    6767        proxyHttpServerBox.parent = proxyGroup; 
    6868        //~DFL dfl.label.Label=proxyHttpPortLabel 
     
    7272        proxyHttpPortLabel.text = "Por&t:"; 
    7373        proxyHttpPortLabel.textAlign = dfl.base.ContentAlignment.MIDDLE_LEFT; 
    74         proxyHttpPortLabel.bounds = dfl.base.Rect(230, 25, 28, 23); 
     74        proxyHttpPortLabel.bounds = dfl.all.Rect(230, 25, 28, 23); 
    7575        proxyHttpPortLabel.parent = proxyGroup; 
    7676        //~DFL OptTextBoxDword:dfl.textbox.TextBox=proxyHttpPortBox 
     
    7878        proxyHttpPortBox.name = "proxyHttpPortBox"; 
    7979        proxyHttpPortBox.enabled = false; 
    80         proxyHttpPortBox.bounds = dfl.base.Rect(268, 25, 48, 23); 
     80        proxyHttpPortBox.bounds = dfl.all.Rect(268, 25, 48, 23); 
    8181        proxyHttpPortBox.parent = proxyGroup; 
    8282        //~Entice Designer 0.8.2pre7 code ends here. 
     
    116116                        proxyHttpPortBox.text = "8080"; 
    117117                } 
     118                else 
     119                { 
     120                    proxyHttpPortBox.text = "8080"; 
     121                } 
    118122                 
    119123                proxyHttpServerBox.focus(); 
     
    133137        with(panel) 
    134138        { 
    135             useProxy = useProxyCheck.checked
     139            useProxy = useProxyCheck.checked && proxyHttpServerBox.textLength
    136140        } 
    137141    } 
  • trunk/win32/entice/ddoptspluginspanel.d

    r101 r102  
    119119     
    120120     
    121     /+ // Old plugin info. 
    122     override void onShow(Tabber tabc, int index) 
    123     { 
    124         super.onShow(tabc, index); 
    125          
    126         if(!_lp) 
    127         { 
    128             _lp = true; 
    129              
    130             with(panel) 
    131             { 
    132                 POLVItem polvi; 
    133                 char[] s; 
    134                 bool rm; 
    135                  
    136                 const char[] REMOVING_DESC = "<Unloading>"; 
    137                  
    138                 foreach(plug; plugins.plugins) 
    139                 { 
    140                     assert(plug.fname.length); 
    141                     rm = isPluginUnloading(plug.fname); 
    142                     if(rm) 
    143                         polvi = new POLVItem(plug.fname, plug.name, REMOVING_DESC); 
    144                     else 
    145                         polvi = new POLVItem(plug.fname, plug.name, plug.desc); 
    146                     pluginView.items.add(polvi); 
    147                     polvi.checked = !rm; 
    148                 } 
    149                  
    150                 foreach(afwe; loadeddapiplugins) 
    151                 { 
    152                     rm = isPluginUnloading(afwe); 
    153                     if(rm) 
    154                         polvi = new POLVItem(afwe, afwe, REMOVING_DESC); 
    155                     else 
    156                         polvi = new POLVItem(afwe, afwe, "API information for " ~ std.path.getName(afwe) ~ "."); 
    157                     pluginView.items.add(polvi); 
    158                     polvi.checked = !rm; 
    159                 } 
    160                  
    161                 foreach(nlpn; notloadedplugins) 
    162                 { 
    163                     if(nlpn.length) // Ends up empty if the plugin gets loaded at some point. 
    164                     { 
    165                         polvi = new POLVItem(nlpn, nlpn, "<Not loaded>"); 
    166                         pluginView.items.add(polvi); 
    167                         polvi.checked = false; 
    168                     } 
    169                 } 
    170                  
    171                 pluginView.itemChecked ~= &pluginView_itemChecked; 
    172             } 
    173         } 
    174     } 
    175     +/ 
    176      
    177121    override void onShow(Tabber tabc, int index) 
    178122    { 
     
    211155                    { 
    212156                        checked = true; 
    213                         if(ddpi.fullpath.length > 5 && !std.string.icmp(".dapi", ddpi.fullpath[$ - 5 .. $])) 
     157                        if(ddpi.fullpath.length > 5 
     158                            && (!std.string.icmp(".dapi", ddpi.fullpath[$ - 5 .. $]) 
     159                                || !std.string.icmp(".json", ddpi.fullpath[$ - 5 .. $]))) 
    214160                        { 
    215161                            polvi = new POLVItem(ddpi.fname, ddpi.fname, "API information for " ~ std.path.getName(ddpi.fname) ~ "."); 
     
    226172                            else 
    227173                            { 
    228                                 polvi = new POLVItem(ddpi.fname, plug.name, "?"); // ? 
     174                                polvi = new POLVItem(ddpi.fname, std.path.getBaseName(ddpi.fname), "?"); // ? 
    229175                                checked = true; 
    230176                            } 
     
    265211    } 
    266212     
    267      
    268     /+ // Old plugin info. 
    269     override void appliedOpts() 
    270     { 
    271         // Update dirty ones.. 
    272         with(panel) 
    273         { 
    274             IRGroup pigrp; 
    275             foreach(idx, lvi; pluginView.items) 
    276             { 
    277                 //if(lvi.tag is lvi) 
    278                 if(lvi.tag) 
    279                 { 
    280                     auto polvi = cast(POLVItem)lvi; 
    281                     if(polvi) 
    282                     { 
    283                         if(!pigrp) 
    284                             pigrp = getRkey().createSubGroup("Load"); 
    285                          
    286                         assert(polvi.fname.length); 
    287                         pigrp.setEntryInt("P:" ~ polvi.fname, polvi.checked ? 1 : 0); 
    288                          
    289                         setPluginUnloading(polvi.fname, !polvi.checked); 
    290                          
    291                         bool asloading = false; 
    292                         if(polvi.checked) 
    293                         { 
    294                             foreach(nlpidx, nlp; notloadedplugins) 
    295                             { 
    296                                  
    297                                 // Note.. must be called AFTER done using notloadedpluginpaths[nlpidx]. 
    298                                 void clearNotLoadedPluginPath() 
    299                                 { 
    300                                     notloadedplugins[nlpidx] = null; // Easier than removing it. 
    301                                     notloadedpluginpaths[nlpidx] = null; // Easier than removing it. 
    302                                 } 
    303                                  
    304                                  
    305                                 if(!std.string.icmp(polvi.fname, nlp)) 
    306                                 { 
    307                                     if(!asloading) 
    308                                     { 
    309                                         // Show as "Loading" so that all the plugins can be loaded blocking. 
    310                                         asloading = true; 
    311                                         //checkchangednote.text = ""; 
    312                                         checkchangednote.foreColor = SystemColors.controlText.blendColor(SystemColors.highlight); 
    313                                         checkchangednote.text = "  Loading plugins..."; 
    314                                         checkchangednote.visible = true; 
    315                                         //checkchangednote.update(); // Show the new text. 
    316                                         Application.doEvents(); // So that dock stuff runs, etc. 
    317                                     } 
    318                                      
    319                                     char[] ext = std.path.getExt(nlp); 
    320                                     if(!std.string.icmp(ext, "dll")) 
    321                                     { 
    322                                         char[] emsg; 
    323                                         Plugin plug; 
    324                                         int errnum; 
    325                                         //msgBox(notloadedpluginpaths[nlpidx], polvi.fname); 
    326                                         emsg = loadDllPlugin(notloadedpluginpaths[nlpidx], plug, false, errnum); 
    327                                         if(emsg.length) 
    328                                         { 
    329                                             msgBox(emsg, "Plugin: " ~ polvi.fname, MsgBoxButtons.OK, MsgBoxIcon.ASTERISK); 
    330                                         } 
    331                                         else 
    332                                         { 
    333                                             if(plug) 
    334                                             { 
    335                                                 clearNotLoadedPluginPath(); 
    336                                                  
    337                                                 registerPlugin(plug); 
    338                                                 signalOnePluginLoaded(plug); 
    339                                             } 
    340                                         } 
    341                                     } 
    342                                     else if(!std.string.icmp(ext, "dapi")) 
    343                                     { 
    344                                         // Can NOT load these in a separate thread from here, because apiinfo.isLoaded was already set, 
    345                                         // and possibly has code wanting to run using it. Need to BLOCK to modify it. 
    346                                          
    347                                         struct APIINFO { public import apiinfo; } 
    348                                          
    349                                         //apiinfo.setUnloaded(); // Oh well, might as well prevent yet another thread... 
    350                                         APIINFO.setUnloaded(); // Oh well, might as well prevent yet another thread... 
    351                                         try 
    352                                         { 
    353                                             // Let other threads notice apiinfo.isLoaded changed, heh... 
    354                                             Application.doEvents(); 
    355                                             struct THD { public import std.thread; } 
    356                                             //Thread.yield(); 
    357                                             THD.Thread.yield(); 
    358                                              
    359                                             //loadApiInfo(notloadedpluginpaths[nlpidx]); 
    360                                             //apiinfo.loadApiInfo(notloadedpluginpaths[nlpidx]); // I don't see how this works but the previous line doesn't... Maybe compiler bug. 
    361                                             APIINFO.loadApiInfo(notloadedpluginpaths[nlpidx]); 
    362                                              
    363                                             loadeddapiplugins ~= nlp; 
    364                                              
    365                                             clearNotLoadedPluginPath(); 
    366                                         } 
    367                                         finally 
    368                                         { 
    369                                             //apiinfo.setLoadedOne(); // Need to restore. 
    370                                             APIINFO.setLoadedOne(); // Need to restore. 
    371                                         } 
    372                                     } 
    373                                     else 
    374                                     { 
    375                                         clearNotLoadedPluginPath(); 
    376                                          
    377                                         msgBox("Unable to start plugin: " ~ polvi.fname); 
    378                                     } 
    379                                     break; 
    380                                 } 
    381                                  
    382                                 Application.doEvents(); // Since it's all loaded blocking... 
    383                             } 
    384                         } 
    385                     } 
    386                 } 
    387             } 
    388         } 
    389          
    390         super.appliedOpts(); 
    391     } 
    392     +/ 
    393213     
    394214    override void appliedOpts() 
     
    434254                                    } 
    435255                                     
    436                                     char[] ext = std.path.getExt(ddplugins[i].fullpath); 
    437                                     if(!std.string.icmp(ext, "dll")) 
     256                                    Plugin plug = null; 
     257                                     
     258                                    if(ddplugins[i].flags & DDPI.BUILTIN) 
    438259                                    { 
    439                                         char[] emsg; 
    440                                         Plugin plug; 
    441                                         int errnum; 
    442                                         //msgBox(ddplugins[i].fullpath, polvi.fname); 
    443                                         emsg = loadDllPlugin(ddplugins[i].fullpath, plug, false, errnum); 
    444                                         if(emsg.length) 
     260                                        plug = getBuiltinPlugin(ddplugins[i].fullpath); 
     261                                        ddplugins[i].flags |= DDPI.LOADED; 
     262                                        registerPlugin(plug); 
     263                                        signalOnePluginLoaded(plug); 
     264                                    } 
     265                                    else 
     266                                    { 
     267                                        char[] ext = std.path.getExt(ddplugins[i].fullpath); 
     268                                        if(!std.string.icmp(ext, "dll")) 
    445269                                        { 
    446                                             msgBox(emsg, "Plugin: " ~ ddplugins[i].fname, MsgBoxButtons.OK, MsgBoxIcon.ASTERISK); 
     270                                            char[] emsg; 
     271                                            int errnum; 
     272                                            //msgBox(ddplugins[i].fullpath, polvi.fname); 
     273                                            emsg = loadDllPlugin(ddplugins[i].fullpath, plug, false, errnum); 
     274                                            if(emsg.length) 
     275                                            { 
     276                                                msgBox(emsg, "Plugin: " ~ ddplugins[i].fname, MsgBoxButtons.OK, MsgBoxIcon.ASTERISK); 
     277                                            } 
     278                                            else 
     279                                            { 
     280                                                if(plug) 
     281                                                { 
     282                                                    ddplugins[i].flags |= DDPI.LOADED; 
     283                                                     
     284                                                    registerPlugin(plug); 
     285                                                    signalOnePluginLoaded(plug); // Needed to tell the plugin "loaded". On startup this is done on a delay all at once. 
     286                                                } 
     287                                            } 
     288                                        } 
     289                                        else if(!std.string.icmp(ext, "dapi") || !std.string.icmp(ext, "json")) 
     290                                        { 
     291                                            // Can NOT load these in a separate thread from here, because apiinfo.isLoaded was already set, 
     292                                            // and possibly has code wanting to run using it. Need to BLOCK to modify it. 
     293                                             
     294                                            struct APIINFO { public import apiinfo; } 
     295                                             
     296                                            //apiinfo.setUnloaded(); // Oh well, might as well prevent yet another thread... 
     297                                            APIINFO.setUnloaded(); // Oh well, might as well prevent yet another thread... 
     298                                            try 
     299                                            { 
     300                                                // Let other threads notice apiinfo.isLoaded changed, heh... 
     301                                                Application.doEvents(); 
     302                                                struct THD { public import std.thread; } 
     303                                                //Thread.yield(); 
     304                                                THD.Thread.yield(); 
     305                                                 
     306                                                //loadApiInfo(ddplugins[i].fullpath); 
     307                                                //apiinfo.loadApiInfo(ddplugins[i].fullpath); // I don't see how this works but the previous line doesn't... Maybe compiler bug. 
     308                                                APIINFO.loadApiInfo(ddplugins[i].fullpath); 
     309                                                 
     310                                                ddplugins[i].flags |= DDPI.LOADED; 
     311                                            } 
     312                                            finally 
     313                                            { 
     314                                                //apiinfo.setLoadedOne(); // Need to restore. 
     315                                                APIINFO.setLoadedOne(); // Need to restore. 
     316                                            } 
    447317                                        } 
    448318                                        else 
    449319                                        { 
    450                                             if(plug) 
    451                                             { 
    452                                                 ddplugins[i].flags |= DDPI.LOADED; 
    453                                                  
    454                                                 registerPlugin(plug); 
    455                                                 signalOnePluginLoaded(plug); // Needed to tell the plugin "loaded". On startup this is done on a delay all at once. 
    456                                             } 
     320                                            ddplugins[i].flags |= DDPI.NOTLOADING; 
     321                                             
     322                                            msgBox("Unable to start plugin: " ~ polvi.fname); 
    457323                                        } 
    458324                                    } 
    459                                     else if(!std.string.icmp(ext, "dapi")) 
     325                                     
    460326                                    { 
    461                                         // Can NOT load these in a separate thread from here, because apiinfo.isLoaded was already set, 
    462                                         // and possibly has code wanting to run using it. Need to BLOCK to modify it. 
    463                                          
    464                                         struct APIINFO { public import apiinfo; } 
    465                                          
    466                                         //apiinfo.setUnloaded(); // Oh well, might as well prevent yet another thread... 
    467                                         APIINFO.setUnloaded(); // Oh well, might as well prevent yet another thread... 
    468                                         try 
     327                                        if(plug && (plug.flags & EnticePluginFlags.MASK_PLUGIN_UNIQUE_FEATURES)) 
    469328                                        { 
    470                                             // Let other threads notice apiinfo.isLoaded changed, heh... 
    471                                             Application.doEvents(); 
    472                                             struct THD { public import std.thread; } 
    473                                             //Thread.yield(); 
    474                                             THD.Thread.yield(); 
    475                                              
    476                                             //loadApiInfo(ddplugins[i].fullpath); 
    477                                             //apiinfo.loadApiInfo(ddplugins[i].fullpath); // I don't see how this works but the previous line doesn't... Maybe compiler bug. 
    478                                             APIINFO.loadApiInfo(ddplugins[i].fullpath); 
    479                                              
    480                                             ddplugins[i].flags |= DDPI.LOADED; 
    481                                         } 
    482                                         finally 
    483                                         { 
    484                                             //apiinfo.setLoadedOne(); // Need to restore. 
    485                                             APIINFO.setLoadedOne(); // Need to restore. 
     329                                            foreach(Plugin onplug; plugins.plugins) 
     330                                            { 
     331                                                if(onplug.pluginid != plug.pluginid) 
     332                                                { 
     333                                                    // Check for overlapping features. 
     334                                                    if((onplug.flags & EnticePluginFlags.MASK_PLUGIN_UNIQUE_FEATURES) 
     335                                                        & (plug.flags & EnticePluginFlags.MASK_PLUGIN_UNIQUE_FEATURES)) 
     336                                                    { 
     337                                                        msgBox("The plugin '" ~ plug.name ~ "' (" ~ plug.fname ~ ")\r\nmay conflict with an existing plugin;\r\nplease restart " ~ TITLE ~ " to resolve any issues", "Plugin Conflict"); 
     338                                                        break; 
     339                                                    } 
     340                                                } 
     341                                            } 
    486342                                        } 
    487343                                    } 
    488                                     else 
    489                                     { 
    490                                         ddplugins[i].flags |= DDPI.NOTLOADING; 
    491                                          
    492                                         msgBox("Unable to start plugin: " ~ polvi.fname); 
    493                                     } 
    494344                                     
    495345                                    Application.doEvents(); // Since it's all loaded blocking... 
     346                                     
    496347                                } 
    497348                            } 
  • trunk/win32/entice/ddprojectmanager.d

    r101 r102  
    318318        if(pe.canContainSubEntries()) 
    319319        { 
    320             TreeNode dn = new EProjectDirNode(pe, sort); 
     320            TreeNode dn = createDirNode(pe, sort); 
    321321            dn.nodes.add(cast(TreeNode)(new EProjectSubItemsLoadingNode())); 
    322322            if(sort) 
     
    331331                if(std.path.fnmatch(pe.name, filter)) 
    332332                { 
    333                     TreeNode fn = new EProjectFileNode(pe.name); 
     333                    TreeNode fn = createFileNode(pe.name); 
    334334                    if(sort) 
    335335                        nodes.add(fn); 
     
    341341        } 
    342342    } 
    343      
    344343     
    345344    void addProjectEntry(inout EProjectEntry pe, bool sort = true) 
     
    447446     
    448447     
     448    protected EProjectNode createFileNode(string name) 
     449    { 
     450        return new EProjectFileNode(name); 
     451    } 
     452     
     453    protected EProjectNode createDirNode(inout EProjectEntry pe, bool sorted) 
     454    { 
     455        return new EProjectDirNode(pe, sorted); 
     456    } 
     457     
     458     
     459    // Adds a list of files, but isn't necessarily a live dir listing. 
    449460    TreeNode loadFileList(char[][] filters, bool sort = true) 
    450461    { 
     
    459470        //TreeNode tn = new EProjectHeaderNode(s); 
    460471        EProjectEntry dpe; 
     472        dpe.project = project; 
    461473        dpe.name = s; 
    462         TreeNode tn = new EProjectDirNode(dpe); 
     474        TreeNode tn = createDirNode(dpe, sort); 
    463475        if(sort) 
    464476            nodes.add(tn); // Need to add it first so adding to it knows to sort. 
     
    478490     
    479491     
    480     // Only works for directory projects. 
    481     void ensureFileAdded(char[] filepath) 
     492    // This implementation works for directory projects by adding new files. 
     493    void fileOpened(char[] filepath) 
    482494    { 
    483495        EProjectDir pdir; 
     
    509521                            if(fn.length) 
    510522                            { 
    511                                 TreeNode nftn = new EProjectFileNode(filepath); 
     523                                TreeNode nftn = createFileNode(filepath); 
    512524                                tn.nodes.add(nftn); 
    513525                                tn.expand(); 
     
    520532        } 
    521533    } 
    522 
    523  
     534     
     535
     536 
  • trunk/win32/entice/design.d

    r101 r102  
    13921392         
    13931393        this(char[] enumTypeName, char[][] enumValues, char[] value, int listX, int listY, int listWidth) 
    1394         in 
    13951394        { 
    13961395            assert(enumValues.length); 
    1397         } 
    1398         body 
    1399         { 
     1396             
    14001397            lfmt = new TextFormat(TextFormatFlags.NO_PREFIX | TextFormatFlags.SINGLE_LINE 
    14011398                | TextFormatFlags.NO_CLIP | TextFormatFlags.LINE_LIMIT); 
     
    15321529             
    15331530            int r = right; 
    1534             int sr = Screen.primaryScreen.workingArea.right; 
     1531            //int sr = Screen.primaryScreen.workingArea.right; 
     1532            int sr = Screen.fromControl(listBox).workingArea.right; 
    15351533            if(r > sr) 
    15361534                left = left - (r - sr); 
  • trunk/win32/entice/designcontrol.d

    r101 r102  
    750750        return dControlSubSelected(dctrl, callback); 
    751751    } 
     752} 
     753 
     754 
     755// if fromTopmost is true, uses dControlAllSelected, otherwise dControlSubSelected. 
     756// Returns true if more than one design control is selected. 
     757bool dControlMultipleSelected(IDesignControl dctrl, bool fromTopmost) 
     758{ 
     759    int count = 0; 
     760     
     761     
     762    bool callback(IDesignControlItem idci) 
     763    { 
     764        if(++count > 1) 
     765            return false; // Stop. 
     766        return true; // Continue. 
     767    } 
     768     
     769     
     770    if(fromTopmost) 
     771        dControlAllSelected(dctrl, &callback); 
     772    else 
     773        dControlSubSelected(dctrl, &callback); 
     774    return count > 1; 
     775} 
     776 
     777// if fromTopmost is true, uses dControlAllSelected, otherwise dControlSubSelected. 
     778// Returns true if at least one design control is selected. 
     779bool dControlAnySelected(IDesignControl dctrl, bool fromTopmost) 
     780{ 
     781    bool any = false; 
     782     
     783     
     784    bool callback(IDesignControlItem idci) 
     785    { 
     786        any = true; 
     787        return false; // Stop. 
     788    } 
     789     
     790     
     791    if(fromTopmost) 
     792        dControlAllSelected(dctrl, &callback); 
     793    else 
     794        dControlSubSelected(dctrl, &callback); 
     795    return any; 
     796} 
     797 
     798 
     799// if fromTopmost is true, uses dControlAllSelected, otherwise dControlSubSelected. 
     800// Returns number of design controls selected. 
     801int dControlCountSelected(IDesignControl dctrl, bool fromTopmost) 
     802{ 
     803    int count = 0; 
     804     
     805     
     806    bool callback(IDesignControlItem idci) 
     807    { 
     808        count++; 
     809        return true; // Continue. 
     810    } 
     811     
     812     
     813    if(fromTopmost) 
     814        dControlAllSelected(dctrl, &callback); 
     815    else 
     816        dControlSubSelected(dctrl, &callback); 
     817    return count; 
    752818} 
    753819 
     
    11651231                } 
    11661232                 
    1167                 dControlUpdateSelect(dctrl, true); 
     1233                bool clearOthers = true; 
     1234                bool setselected = true; 
     1235                version(ENTICE_MULTISEL) 
     1236                { 
     1237                    if(Control.modifierKeys & Keys.CONTROL) 
     1238                    { 
     1239                        clearOthers = false; 
     1240                        IDesignControlItem othersel = null; 
     1241                        dControlAllSelected(dctrl, 
     1242                            (IDesignControlItem idci) 
     1243                            { 
     1244                                if(idci is dctrl) 
     1245                                { 
     1246                                    // Try to find one that's not this one. 
     1247                                    return true; // Continue. 
     1248                                } 
     1249                                othersel = idci; 
     1250                                return false; // Break. 
     1251                            }); 
     1252                        if(othersel && dctrl.itemParent !is othersel.itemParent) 
     1253                        { 
     1254                            // Can't multi-sel if different parents. 
     1255                            return; 
     1256                        } 
     1257                        if(dctrl.isItemSelected) 
     1258                        { 
     1259                            // If it's already selected, try to un-select, 
     1260                            // but only if there are others selected. 
     1261                            if(othersel) 
     1262                            { 
     1263                                assert(othersel !is dctrl); 
     1264                                setselected = false; 
     1265                            } 
     1266                        } 
     1267                    } 
     1268                } 
     1269                dControlUpdateSelect(dctrl, setselected, clearOthers); 
     1270                if(!setselected) 
     1271                    return; 
    11681272                version(NOFOCUSDESIGNITEM) 
    11691273                { 
     
    12471351                    else 
    12481352                    { 
    1249                         Rect r; 
    1250                         dctrl.getItemBounds(r); 
    1251                         r.x += dlastpt.x - dorigpt.x; 
    1252                         r.y += dlastpt.y - dorigpt.y; 
    1253                         dctrl.setItemBounds(r); 
     1353                        int diffx = dlastpt.x - dorigpt.x; 
     1354                        int diffy = dlastpt.y - dorigpt.y; 
     1355                        version(ENTICE_MULTISEL) 
     1356                        { 
     1357                            IDesignControl dselscan = cast(IDesignControl)dctrl.itemParent; 
     1358                            if(!dselscan) 
     1359                            { 
     1360                                dselscan = dctrl; 
     1361                            } 
     1362                            dControlSubSelected(dselscan, 
     1363                                (IDesignControlItem idci) 
     1364                                { 
     1365                                    Rect idciRect; 
     1366                                    idci.getItemBounds(idciRect); 
     1367                                    idciRect.x += diffx; 
     1368                                    idciRect.y += diffy; 
     1369                                    idci.setItemBounds(idciRect); 
     1370                                    return true; // Continue. 
     1371                                }); 
     1372                        } 
     1373                        else 
     1374                        { 
     1375                            Rect r; 
     1376                            dctrl.getItemBounds(r); 
     1377                            r.x += diffx; 
     1378                            r.y += diffy; 
     1379                            dctrl.setItemBounds(r); 
     1380                        } 
    12541381                    } 
    12551382                } 
  • trunk/win32/entice/dfldesigner.d

    r101 r102  
    88    std.date; 
    99 
    10 private import dfl.all, dfl.winapi, dfl.utf; 
     10private import dfl.all, dfl.internal.winapi, dfl.internal.utf; 
    1111private import dfl.scintilla, dfl.cpp.scintilla, dfl.cpp.scilexer; 
    1212 
    1313import rgroup, rdflregistry, rini; 
     14 
     15import promptbox; 
    1416 
    1517private import winapi; 
     
    2830import waitmanager, dirchanges, plugins; 
    2931import projectmanager, ddprojectmanager; 
     32import ddoptscompilerpanel; 
    3033version(ADVANCED_FIND) 
    3134    import advfindpanel; 
     35import compile; 
     36import process; 
    3237 
    3338 
     
    6368const char[] TITLE = "Entice Designer"; 
    6469const char[] SAVENAME = "Entice"; 
    65 const char[] VERSION = "X"; //"0.8.6pre4"; // Compiled with: (DMD 1.028) - (DFL 0.9.7+snapshot) 
     70const char[] VERSION = "0.8.6pre6"; // Compiled with: (DMD 1.060) - (DFL 0.9.8+snapshot) 
    6671const char[] FULLTITLE = TITLE ~ " " ~ VERSION; 
    67 const char[] COPYRIGHT_STRING_YEARS = "Copyright © 2004-2008"; 
     72const char[] COPYRIGHT_STRING_YEARS = "Copyright © 2004-2010"; 
    6873const char[] AUTHOR = "Christopher E. Miller"; 
    6974 
     
    136141bool reallyClosing = false; 
    137142bool apprun = false; 
    138 char[] localdir; // Usually AppData\Entice. 
     143char[] localdir; // Usually AppData\Entice 
    139144char[] configFilePath; 
    140145//bool killregstuff = false; 
     
    150155// To-do: get filter from registry, per-project, or fallback to global. 
    151156char[][] fileListFilter = ["*.d"[], "*.di", "*.txt", "*.bat", "*.c", "*.h", "*.cpp", "*.cxx", "*.hpp"]; 
     157 
     158 
     159// Note: this can prompt a dialog or throw an exception. 
     160void ensureCompiler(bool allowPrompt = true) 
     161{ 
     162    if(optDmdLocation.length <= 3 || dmdwindowsbindir.length <= 3) 
     163    { 
     164        if(allowPrompt) 
     165        { 
     166            if(mainForm !is null) 
     167            { 
     168                status("Please setup the compiler..."); 
     169                openCompilerConfig(); 
     170            } 
     171        } 
     172         
     173        if(optDmdLocation.length <= 3 || dmdwindowsbindir.length <= 3) 
     174        { 
     175            throw new Exception("Compiler not setup"); 
     176        } 
     177         
     178        assert(optDmdLocation.length > 0); 
     179        assert(dmdwindowsbindir.length > 0); 
     180    } 
     181    assert(optDmdLocation.length > 0); 
     182    assert(dmdwindowsbindir.length > 0); 
     183} 
     184 
     185bool isCompilerSetup() 
     186{ 
     187    if(optDmdLocation.length <= 3 || dmdwindowsbindir.length <= 3) 
     188    { 
     189        return false; 
     190    } 
     191    return true; 
     192} 
     193 
     194 
     195void openCompilerConfig() 
     196{ 
     197    mainForm.n(2207461002); // Compiler tab. 
     198} 
     199 
     200void openCompilerConfig(string setcompilerdir) 
     201{ 
     202    mainForm.n(2207461002, // Compiler tab. 
     203        (DdOptionsForm optsform) 
     204        { 
     205            int selidx = optsform.tabs.selectedIndex; 
     206            if(-1 != selidx) 
     207            { 
     208                auto ctab = cast(CompilerOptTab)optsform.tabs.tabs[selidx]; 
     209                if(ctab) 
     210                { 
     211                    ctab.setDmdLocation(setcompilerdir); 
     212                } 
     213            } 
     214        }); 
     215} 
    152216 
    153217 
     
    306370 
    307371void addEntity(Entity ent) 
    308 in 
    309372{ 
    310373    assert(findEntity(ent) == -1); // That Entity was already added! 
    311 
    312 body 
    313 
     374     
    314375    if(autoHideStartPage && !startPageClosed) 
    315376    { 
     
    582643            if(fp.length) 
    583644            { 
    584                 fp = dfl.utf.getFullPathName(fp); 
     645                fp = dfl.internal.utf.getFullPathName(fp); 
    585646                 
    586647                //filePath = fp; // Causes changes, not needed if file is closing. 
     
    634695     
    635696    CLOSE_ALL = 1, // Closes all tabs in this entity when just this tab is closed. 
     697    ALLOW_DETACH = 2, 
    636698} 
    637699 
     
    662724     
    663725     
    664     this(Entity ent, char[] text
    665     { 
    666         super(text); 
     726    this(Entity ent, char[] text, bool detached = false
     727    { 
     728        super(text, detached); 
    667729         
    668730        ent.etabs ~= this; 
     
    795857     
    796858     
     859    //@ 
    797860    void _tsApply() 
    798861    { 
     
    11781241 
    11791242 
     1243// returns true if handled. 
     1244// line won't be escaped. 
     1245bool doubleclickedStatusOpenFile(string line) 
     1246{ 
     1247    if(mainForm) 
     1248    { 
     1249        size_t iw; 
     1250        size_t lparen = 0, rparen = 0, colon = 0; 
     1251        for(iw = 0; iw < line.length; iw++) 
     1252        { 
     1253            if('(' == line[iw]) 
     1254            { 
     1255                lparen = iw; 
     1256                rparen = 0; 
     1257            } 
     1258            else if(')' == line[iw]) 
     1259            { 
     1260                if(lparen) 
     1261                    rparen = iw; 
     1262            } 
     1263            else if(':' == line[iw] && iw > 1) 
     1264            { 
     1265                string fn; 
     1266                uint linnum; 
     1267                if(lparen && rparen) 
     1268                { 
     1269                    fn = line[0 .. lparen]; 
     1270                    try 
     1271                    { 
     1272                        linnum = std.conv.toUint(line[lparen + 1 .. rparen]); 
     1273                    } 
     1274                    catch 
     1275                    { 
     1276                    } 
     1277                } 
     1278                else if(colon) 
     1279                { 
     1280                    fn = line[0 .. colon]; 
     1281                } 
     1282                else 
     1283                { 
     1284                    break; 
     1285                } 
     1286                fn = fn.dup; 
     1287                 
     1288                auto altdown = Control.modifierKeys & Keys.ALT; 
     1289                 
     1290                if(mainForm) 
     1291                { 
     1292                    EditorTab etab; 
     1293                     
     1294                    mainForm.doOpen(fn, true); // wantEditor = true 
     1295                    etab = cast(EditorTab)getCurrentTab(); 
     1296                    if(!etab) 
     1297                        break; 
     1298                    //if(etab is this) 
     1299                    //  break; 
     1300                     
     1301                    if(linnum) 
     1302                    { 
     1303                        Application.doEvents(); 
     1304                        if(altdown) 
     1305                        { 
     1306                            //EditorTab etab = cast(EditorTab)getCurrentTab(); 
     1307                            //if(etab) 
     1308                            { 
     1309                                etab.switchToOppositeView(); 
     1310                                Application.doEvents(); // ! 
     1311                            } 
     1312                        } 
     1313                        mainForm.doGotoLine(etab.asci, linnum); 
     1314                        //Application.doEvents(); 
     1315                        //etab.asci.select(); 
     1316                        etab.asci.delayInvoke( 
     1317                            function(Control cc, size_t[] params) 
     1318                            { 
     1319                                cc.select(); 
     1320                            }, null); 
     1321                    } 
     1322                } 
     1323                 
     1324                break; 
     1325            } 
     1326        } 
     1327    } 
     1328    return false; 
     1329} 
     1330 
     1331 
    11801332class ModalBox: TextBox 
    11811333{ 
     
    22072359    // If a file is already being notified of changes, it is removed in favor of the new one. 
    22082360    final void notifyChanges(char[] filepath) 
    2209     in 
    22102361    { 
    22112362        assert(std.path.isabs(filepath) || r"\\" == filepath[0 .. 2]); 
    2212     } 
    2213     body 
    2214     { 
     2363         
    22152364        noNotifyChanges(); 
    22162365         
     
    22192368            // Should it watch for FILE_NOTIFY_CHANGE_LAST_WRITE ? 
    22202369            // Note: ReadDirectoryChangesW() can tell you exactly what file/dir changed, but is only supported on NT+. 
    2221             hfchange = dfl.utf.findFirstChangeNotification(getDirName(filepath), FALSE, 
     2370            hfchange = dfl.internal.utf.findFirstChangeNotification(getDirName(filepath), FALSE, 
    22222371                FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE); 
    22232372            if(INVALID_HANDLE_VALUE == hfchange) 
     
    23652514                try 
    23662515                { 
     2516                    char[] ext = std.path.getExt(txt); 
    23672517                    // To-do: cache this extension info... accessing this part of the registry is usually slow as hell. 
    2368                     auto rk = Registry.classesRoot.openSubKey("." ~ std.path.getExt(txt)); 
     2518                    auto rk = Registry.classesRoot.openSubKey("." ~ ext); 
    23692519                    if(rk) 
    23702520                    { 
     
    23822532                        } 
    23832533                    } 
     2534                    if(!moreinfo.length) 
     2535                    { 
     2536                        switch(ext) 
     2537                        { 
     2538                            case "d": 
     2539                                moreinfo = "D Source File"; 
     2540                                break; 
     2541                            case "di": 
     2542                                moreinfo = "D Interface File"; 
     2543                                break; 
     2544                            case "lua", "java", "scala", "tcl": 
     2545                                moreinfo = std.string.capitalize(ext) ~ " Source File"; 
     2546                                break; 
     2547                            case "c", "json", "xml", "vb", "php": 
     2548                                moreinfo = std.string.toupper(ext) ~ " Source File"; 
     2549                                break; 
     2550                            case "cs": 
     2551                                moreinfo = "C# Source File"; 
     2552                                break; 
     2553                            case "cpp": 
     2554                                moreinfo = "C++ Source File"; 
     2555                                break; 
     2556                            case "rb": 
     2557                                moreinfo = "Ruby Source File"; 
     2558                                break; 
     2559                            case "py": 
     2560                                moreinfo = "Python Source File"; 
     2561                                break; 
     2562                            case "pl": 
     2563                                moreinfo = "Perl Source File"; 
     2564                                break; 
     2565                            default: 
     2566                                moreinfo = std.string.toupper(ext) ~ " File"; 
     2567                        } 
     2568                    } 
    23842569                } 
    23852570                catch(Object e) 
     
    27102895     
    27112896     
     2897    PropPanelTab[] designtabs = null; 
     2898     
     2899     
     2900    static class PropertiesPropPanelTab: PropPanelTab 
     2901    { 
     2902        this() 
     2903        { 
     2904            super("Properties"); 
     2905        } 
     2906    } 
     2907     
     2908    static class EventsPropPanelTab: PropPanelTab 
     2909    { 
     2910        this() 
     2911        { 
     2912            super("Events"); 
     2913        } 
     2914    } 
     2915     
     2916     
    27122917    override void onShow(Tabber tabc, int index) 
    27132918    { 
    2714         //_tsPropTabs = [ new PropPanelTab("Properties"), new PropPanelTab("Events") ]; 
     2919        /+if(designtabs is null) 
     2920        { 
     2921            designtabs = [ new PropertiesPropPanelTab(), new EventsPropPanelTab() ]; 
     2922        }+/ 
    27152923        _tsPropTabs = propTabs; 
     2924        //_tsPropTabs = designtabs; 
    27162925         
    27172926        super.onShow(tabc, index); 
     
    27642973     
    27652974     
    2766     private IDesignControlItem getSingleSelItem() 
    2767     { 
    2768         IDesignControlItem selItem; 
    2769          
    2770         bit onItem(IDesignControlItem idci) 
    2771         { 
    2772             if(idci.isItemSelected()) 
    2773             { 
    2774                 if(selItem) // 2 items selected; abort whole thing. 
    2775                 { 
    2776                     selItem = null; 
    2777                     return false; // Stop. 
    2778                 } 
    2779                 selItem = idci; 
    2780             } 
    2781             idci.getItems(&onItem); 
    2782             return true; // Continue. 
    2783         } 
    2784          
    2785         designControl.getItems(&onItem); 
    2786         return selItem; 
    2787     } 
    2788      
    2789      
    2790     private void doDelSelItem(IDesignControlItem selItem) 
    2791     { 
    2792         selItem.itemDeleteKey(); // ? 
    2793     } 
    2794      
    2795      
    2796     private IDesignControlItem doCbSelItemCopy() 
    2797     { 
    2798         IDesignControlItem selItem; 
    2799         selItem = getSingleSelItem(); 
    2800         if(selItem) 
    2801         { 
    2802             char[] cpy, s, s2, s3; 
    2803              
    2804             char[] libname = selItem.getLibName(); 
    2805              
    2806             cpy = libname // Lib name. 
    2807                 ~ "\r\nControl" // Type of design item. 
    2808                 ~ "\r\n" ~ designControl.getDesignTypeName(); // Top-design item. 
    2809              
    2810             auto selparent = selItem.itemParent(); 
    2811             if(selparent) 
    2812             { 
    2813                 s = selparent.getDesignTypeName(); 
    2814                 s2 = selparent.getOtherDesignTypeName(); 
     2975    private void doSelItemsDelete() 
     2976    { 
     2977        if(designControl) 
     2978        { 
     2979            // Just send the delete key to any one, 
     2980            // it'll delete all selected. 
     2981            designControl.itemDeleteKey(); 
     2982        } 
     2983    } 
     2984     
     2985     
     2986    private void doCbSelItemsCopy() 
     2987    { 
     2988        if(!designControl) 
     2989            return; 
     2990        char[] libname = designControl.getLibName(); 
     2991        char[] cpy = libname // Lib name. 
     2992            ~ "\r\nControl" // Type of design item. 
     2993            ~ "\r\n" ~ designControl.getDesignTypeName(); // Top-design item. 
     2994        int numselected = 0; 
     2995        dControlSubSelected(designControl, 
     2996            (IDesignControlItem selItem) 
     2997            { 
     2998                if(selItem is designControl) 
     2999                { 
     3000                    return true; // Continue. 
     3001                } 
     3002                numselected++; 
     3003                 
     3004                char[] s, s2, s3; 
     3005                 
     3006                auto selparent = selItem.itemParent(); 
     3007                 
     3008                if(numselected == 1) 
     3009                { 
     3010                    if(selparent) 
     3011                    { 
     3012                        s = selparent.getDesignTypeName(); 
     3013                        s2 = selparent.getOtherDesignTypeName(); 
     3014                        if(s != s2) 
     3015                            s = s2 ~ ":" ~ s; 
     3016                        cpy ~= "\r\n" ~ s; // Copied item's parent type. 
     3017                    } 
     3018                    else 
     3019                    { 
     3020                        cpy ~= "\r\n"; // Shouldn't happen... 
     3021                    } 
     3022                     
     3023                    cpy ~= "\r\n-"; // Separator. 
     3024                } 
     3025                 
     3026                s = selItem.getDesignTypeName(); 
     3027                s2 = selItem.getOtherDesignTypeName(); 
    28153028                if(s != s2) 
    28163029                    s = s2 ~ ":" ~ s; 
    2817                 cpy ~= "\r\n" ~ s; // Copied item's parent type. 
    2818             } 
    2819             else 
    2820             { 
    2821                 cpy ~= "\r\n"; // Shouldn't happen... 
    2822             } 
    2823              
    2824             cpy ~= "\r\n-"; // Separator. 
    2825              
    2826             s = selItem.getDesignTypeName(); 
    2827             s2 = selItem.getOtherDesignTypeName(); 
    2828             if(s != s2) 
    2829                 s = s2 ~ ":" ~ s; 
    2830             s3 = selItem.getMoreTypeInfo(); 
    2831             if(s3.length) 
    2832                 s = s ~ " " ~ s3; 
    2833             cpy ~= "\r\n" ~ s; // Copied item's type. 
    2834              
    2835             selItem.foreachPropSave( 
    2836                 (char[] saveString) 
    2837                 { 
    2838                     cpy ~= "\r\n" ~ saveString; // Item properties. 
    2839                 }, null); 
    2840              
    2841             /+ 
    2842             selItem.getItems( 
    2843                 (IDesignControlItem onItem) 
    2844                 { 
    2845                      
    2846                     return true; // Continue. 
    2847                 }); 
    2848             +/ 
    2849              
    2850             cpy ~= "\r\n-"; // Separator. 
    2851              
     3030                s3 = selItem.getMoreTypeInfo(); 
     3031                if(s3.length) 
     3032                    s = s ~ " " ~ s3; 
     3033                cpy ~= "\r\n" ~ s; // Copied item's type. 
     3034                 
     3035                selItem.foreachPropSave( 
     3036                    (char[] saveString) 
     3037                    { 
     3038                        cpy ~= "\r\n" ~ saveString; // Item properties. 
     3039                    }, null); 
     3040                 
     3041                /+ 
     3042                selItem.getItems( 
     3043                    (IDesignControlItem onItem) 
     3044                    { 
     3045                         
     3046                        return true; // Continue. 
     3047                    }); 
     3048                +/ 
     3049                 
     3050                cpy ~= "\r\n-"; // Separator. 
     3051                 
     3052                return true; // Continue. 
     3053            }); 
     3054        if(numselected) 
     3055        { 
    28523056            DataObject clp = new DataObject; 
    28533057            clp.setData(CLIPBOARD_FORMAT, Data(cpy)); 
     3058            //clp.setData(dfl.data.DataFormats.text, Data(cpy)); // Testing. 
    28543059            Clipboard.setDataObject(clp); 
    28553060        } 
    2856         return selItem; 
    28573061    } 
    28583062     
     
    28603064    private void menu_editCut() 
    28613065    { 
    2862         IDesignControlItem selItem; 
    2863         selItem = doCbSelItemCopy(); 
    2864         if(selItem) 
    2865         { 
    2866             doDelSelItem(selItem); 
    2867         } 
     3066        doCbSelItemsCopy(); 
     3067        doSelItemsDelete(); 
    28683068    } 
    28693069     
     
    28713071    private void menu_editCopy() 
    28723072    { 
    2873         doCbSelItemCopy(); 
     3073        doCbSelItemsCopy(); 
    28743074    } 
    28753075     
     
    28923092name = "button1"; 
    28933093text = "OK"; 
    2894 bounds = dfl.base.Rect(168, 216, 75, 23); 
     3094bounds = dfl.all.Rect(168, 216, 75, 23); 
    28953095- 
    28963096 
     
    29063106backColor = dfl.drawing.Color(0, 164, 0); 
    29073107dock = dfl.control.DockStyle.FILL; 
    2908 bounds = dfl.base.Rect(4, 23, 192, 73); 
     3108bounds = dfl.all.Rect(4, 23, 192, 73); 
    29093109- 
    29103110    +/ 
     
    29403140            return false; 
    29413141         
    2942         IDesignControlItem selItem; 
    2943         selItem = getSingleSelItem(); 
    2944         if(!selItem) 
    2945         { 
    2946             //msgBox("Cannot determine where to paste"); 
    2947             //return true; 
    2948             selItem = designControl; 
    2949         } 
     3142        IDesignControlItem selItem = designControl; 
     3143        dControlSubSelected(designControl, 
     3144            (IDesignControlItem idci) 
     3145            { 
     3146                if(selItem) 
     3147                { 
     3148                    // If more than one selected, use their parent. 
     3149                    selItem = selItem.itemParent; 
     3150                    if(!selItem) 
     3151                        selItem = designControl; 
     3152                    return false; // Break. 
     3153                } 
     3154                selItem = idci; 
     3155                return true; // Continue. 
     3156            }); 
    29503157         
    29513158        IDesignControl dctrlSel; 
     
    29593166            { 
    29603167                huh: 
    2961                 //msgBox("Cannot determine where to paste"); 
    2962                 //return true; 
    29633168                selItem = designControl; 
    29643169                break; 
     
    30283233            goto no_info; 
    30293234         
    3030         Control nc; 
    3031         Token tok; 
    3032         Token[] toks = new Token[2]; 
    3033         toks[0].type = TokenType.IDENT; 
    3034         toks[0].str = "_paste"; 
    3035         toks[1].type = TokenType.DOT; 
    3036         toks[1].str = "."; 
    3037         char[] tname, fcname; 
    3038         Parser par = new Parser("Paste", null); 
    3039         for(++iw; iw != plines.length; iw++) 
    3040         { 
    3041             if(!tname.length) 
    3042             { 
    3043                 tname = plines[iw]; 
    3044                  
    3045                 int i; 
    3046                  
    3047                 char[] moreTypeInfo = null; 
    3048                 i = std.string.find(tname, ' '); 
    3049                 if(-1 != i) 
    3050                 { 
    3051                     moreTypeInfo = tname[i + 1 .. $]; 
    3052                     tname = tname[0 .. i]; 
    3053                 } 
    3054                  
    3055                 i = std.string.find(tname, ':'); 
    3056                 bool by; 
    3057                 if(-1 == i) 
    3058                     by = op.onSubItem(libname, tname, tname, moreTypeInfo, "Pasted" ~ getIdentifier(tname)); 
     3235        int numpasted = 0; 
     3236        paste_all: 
     3237        while(iw < plines.length) 
     3238        { 
     3239            Control nc; 
     3240            Token tok; 
     3241            Token[] toks = new Token[2]; 
     3242            toks[0].type = TokenType.IDENT; 
     3243            toks[0].str = "_paste"; 
     3244            toks[1].type = TokenType.DOT; 
     3245            toks[1].str = "."; 
     3246            char[] tname, fcname; 
     3247            Parser par = new Parser("Paste", null); 
     3248            for(++iw;; iw++) 
     3249            { 
     3250                if(iw >= plines.length) 
     3251                    break; 
     3252                if(!tname.length) 
     3253                { 
     3254                    tname = plines[iw]; 
     3255                     
     3256                    int i; 
     3257                     
     3258                    char[] moreTypeInfo = null; 
     3259                    i = std.string.find(tname, ' '); 
     3260                    if(-1 != i) 
     3261                    { 
     3262                        moreTypeInfo = tname[i + 1 .. $]; 
     3263                        tname = tname[0 .. i]; 
     3264                    } 
     3265                     
     3266                    i = std.string.find(tname, ':'); 
     3267                    bool by; 
     3268                    if(-1 == i) 
     3269                        by = op.onSubItem(libname, tname, tname, moreTypeInfo, "Pasted" ~ getIdentifier(tname)); 
     3270                    else 
     3271                        by = op.onSubItem(libname, tname[i + 1 .. tname.length], tname[0 .. i], moreTypeInfo, "Pasted" ~ getIdentifier(tname[0 .. i])); 
     3272                    if(!by) 
     3273                    { 
     3274                        msgBox("Unable to paste unknown design item"); 
     3275                        return true; 
     3276                    } 
     3277                     
     3278                    nc = op.dctrl; 
     3279                    nc.visible = false; 
     3280                    nc.parent = selDfl.getControl(); 
     3281                } 
    30593282                else 
    3060                     by = op.onSubItem(libname, tname[i + 1 .. tname.length], tname[0 .. i], moreTypeInfo, "Pasted" ~ getIdentifier(tname[0 .. i])); 
    3061                 if(!by) 
    3062                 { 
    3063                     msgBox("Unable to paste unknown design item"); 
    3064                     return true; 
    3065                 } 
    3066                  
    3067                 nc = op.dctrl; 
    3068                 nc.visible = false; 
    3069                 nc.parent = selDfl.getControl(); 
    3070             } 
    3071             else 
    3072             { 
    3073                 if("-" == plines[iw]) 
    3074                     break; 
    3075                  
    3076                 par.reset(); 
    3077                 par.source = plines[iw]; 
    3078                  
    3079                 toks = toks[0 .. 2]; 
    3080                 for(;;) 
    3081                 { 
    3082                     par.getToken(tok); 
    3083                     if(TokenType.EOF == tok.type || TokenType.EOS == tok.type) 
     3283                { 
     3284                    if("-" == plines[iw]) 
    30843285                        break; 
    3085                     toks ~= tok; 
    3086                 } 
    3087                  
    3088                 if(toks.length) 
    3089                 { 
    3090                     switch(toks[2].str
     3286                     
     3287                   par.reset(); 
     3288                   par.source = plines[iw]; 
     3289                    
     3290                   toks = toks[0 .. 2]; 
     3291                    for(;;
    30913292                    { 
    3092                         case "name": 
    3093                            fcname = toks[4].str; 
     3293                        par.getToken(tok); 
     3294                        if(TokenType.EOF == tok.type || TokenType.EOS == tok.type) 
    30943295                            break; 
    3095                          
    3096                         case "dock": 
    3097                         //case "bounds", "size", "clientSize", "location": 
    3098                             break; 
    3099                          
    3100                         default: ; 
    3101                             if(toks[2].str.length && toks[2].str[0] != '@') // Ones starting with @ are special for forward compatible. 
    3102                             { 
    3103                                 op.onSubItemPropTokens(toks); 
    3104                             } 
     3296                        toks ~= tok; 
    31053297                    } 
    3106                 } 
    3107             } 
    3108         } 
    3109          
    3110         if(nc) 
    3111         { 
    3112             //if(pasteX >= int.max && pasteY >= int.max) 
    3113             if(pasteX >= short.max && pasteY >= short.max) 
    3114             { 
    3115                 pasteX = nc.left; 
    3116                 pasteY = nc.top; 
    3117             } 
    3118              
    3119             int postries = 0; 
    3120             //bool atzero; 
    3121             bool samepos; 
    3122             trythispos: 
    3123             //atzero = false; 
    3124             samepos = false; 
    3125             selItem.getItems( 
    3126                 (IDesignControlItem idci) 
    3127                 { 
    3128                     if(idci != cast(IDesignControlItem)op.idctrl) 
     3298                     
     3299                    if(toks.length) 
    31293300                    { 
    3130                         Rect sr; 
    3131                         idci.getItemBounds(sr); 
    3132                         /+ 
    3133                         if(sr.x < 16 && sr.y < 16 
    3134                             && sr.x >= -16 && sr.y >= -16) 
    3135                             atzero = true; 
    3136                         +/ 
    3137                         if(sr.x < pasteX + 16 && sr.y < pasteY + 16 
    3138                             && sr.x > pasteX - 16 && sr.y > pasteY - 16) 
    3139                             samepos = true; 
    3140                         if(/+ atzero && +/ samepos) 
    3141                             return false; // Stop. 
    3142                     } 
    3143                     return true; // Continue. 
    3144                 }); 
    3145             int j = gridSize; 
    3146             if(j <= 0) // Shouldn't happen. 
    3147                 j = 1; 
    3148             if(samepos) 
    3149             { 
    3150                 /+if(atzero) 
    3151                 { 
    3152                 } 
    3153                 else+/ 
    3154                 { 
    3155                     //nc.location = Point(pasteX, pasteY); 
    3156                     if(isGridValueDisabled(gridSize)) 
    3157                     { 
    3158                         pasteX += 24; 
    3159                         pasteY += 24; 
    3160                     } 
    3161                     else 
    3162                     { 
    3163                         int _x = pasteX + 24, _y = pasteY + 24; 
    3164                         while(pasteX < _x) 
     3301                        switch(toks[2].str) 
    31653302                        { 
    3166                             pasteX += j; 
    3167                         } 
    3168                         while(pasteY < _y) 
    3169                         { 
    3170                             pasteY += j; 
     3303                            case "name": 
     3304                                fcname = toks[4].str; 
     3305                                break; 
     3306                             
     3307                            case "dock": 
     3308                            //case "bounds", "size", "clientSize", "location": 
     3309                                break; 
     3310                             
     3311                            default: ; 
     3312                                if(toks[2].str.length && toks[2].str[0] != '@') // Ones starting with @ are special for forward compatible. 
     3313                                { 
     3314                                    op.onSubItemPropTokens(toks); 
     3315                                } 
    31713316                        } 
    31723317                    } 
    31733318                } 
     3319            } 
     3320             
     3321            if(nc) 
     3322            { 
     3323                //if(pasteX >= int.max && pasteY >= int.max) 
     3324                if(pasteX >= short.max && pasteY >= short.max) 
     3325                { 
     3326                    pasteX = nc.left; 
     3327                    pasteY = nc.top; 
     3328                } 
    31743329                 
    3175                 if(++postries < 32) 
    3176                     goto trythispos; 
    3177             } 
    3178             Rect cr; 
    3179             selItem.getItemBounds(cr); 
    3180             if(pasteX > cr.width - nc.width || pasteY > cr.height - nc.width) 
    3181             { 
    3182                 //pasteX = 0; 
    3183                 //pasteY = 0; 
    3184                 int px = pasteX - j, py = pasteY - j; 
    3185                 pasteX -= j << 1; 
    3186                 pasteY -= j << 1; 
    3187                 for(;;) 
    3188                 { 
    3189                     if(pasteX < 0) 
     3330                int postries = 0; 
     3331                //bool atzero; 
     3332                bool samepos; 
     3333                trythispos: 
     3334                //atzero = false; 
     3335                samepos = false; 
     3336                selItem.getItems( 
     3337                    (IDesignControlItem idci) 
    31903338                    { 
     3339                        if(idci != cast(IDesignControlItem)op.idctrl) 
     3340                        { 
     3341                            Rect sr; 
     3342                            idci.getItemBounds(sr); 
     3343                            /+ 
     3344                            if(sr.x < 16 && sr.y < 16 
     3345                                && sr.x >= -16 && sr.y >= -16) 
     3346                                atzero = true; 
     3347                            +/ 
     3348                            if(sr.x < pasteX + 16 && sr.y < pasteY + 16 
     3349                                && sr.x > pasteX - 16 && sr.y > pasteY - 16) 
     3350                                samepos = true; 
     3351                            if(/+ atzero && +/ samepos) 
     3352                                return false; // Stop. 
     3353                        } 
     3354                        return true; // Continue. 
     3355                    }); 
     3356                int j = gridSize; 
     3357                if(j <= 0) // Shouldn't happen. 
     3358                    j = 1; 
     3359                if(samepos) 
     3360                { 
     3361                    /+if(atzero) 
     3362                    { 
     3363                    } 
     3364                    else+/ 
     3365                    { 
     3366                        //nc.location = Point(pasteX, pasteY); 
     3367                        if(isGridValueDisabled(gridSize)) 
     3368                        { 
     3369                            pasteX += 24; 
     3370                            pasteY += 24; 
     3371                        } 
     3372                        else 
     3373                        { 
     3374                            int _x = pasteX + 24, _y = pasteY + 24; 
     3375                            while(pasteX < _x) 
     3376                            { 
     3377                                pasteX += j; 
     3378                            } 
     3379                            while(pasteY < _y) 
     3380                            { 
     3381                                pasteY += j; 
     3382                            } 
     3383                        } 
     3384                    } 
     3385                     
     3386                    if(++postries < 32) 
     3387                        goto trythispos; 
     3388                } 
     3389                Rect cr; 
     3390                selItem.getItemBounds(cr); 
     3391                if(pasteX > cr.width - nc.width || pasteY > cr.height - nc.width) 
     3392                { 
     3393                    //pasteX = 0; 
     3394                    //pasteY = 0; 
     3395                    int px = pasteX - j, py = pasteY - j; 
     3396                    pasteX -= j << 1; 
     3397                    pasteY -= j << 1; 
     3398                    for(;;) 
     3399                    { 
     3400                        if(pasteX < 0) 
     3401                        { 
     3402                            if(pasteY < 0) 
     3403                            { 
     3404                                pasteX = px; 
     3405                                pasteY = py; 
     3406                                break; 
     3407                            } 
     3408                            py = pasteY; 
     3409                            pasteY -= j; 
     3410                            continue; 
     3411                        } 
    31913412                        if(pasteY < 0) 
    31923413                        { 
    3193                             pasteX = px
    3194                             pasteY = py
    3195                             break
     3414                            px = pasteX
     3415                            pasteX -= j
     3416                            continue
    31963417                        } 
     3418                        px = pasteX; 
    31973419                        py = pasteY; 
     3420                        pasteX -= j; 
    31983421                        pasteY -= j; 
    3199                         continue; 
    32003422                    } 
    3201                     if(pasteY < 0) 
    3202                     { 
    3203                         px = pasteX; 
    3204                         pasteX -= j; 
    3205                         continue; 
    3206                     } 
    3207                     px = pasteX; 
    3208                     py = pasteY; 
    3209                     pasteX -= j; 
    3210                     pasteY -= j; 
     3423                     
     3424                    if(++postries < 32) 
     3425                        goto trythispos; 
     3426                } 
     3427                if(pasteX < 0) 
     3428                { 
     3429                    pasteX = 0; 
     3430                } 
     3431                if(pasteY < 0) 
     3432                { 
     3433                    pasteY = 0; 
     3434                } 
     3435                if(nc.left != pasteX || nc.top != pasteY) 
     3436                { 
     3437                    //nc.location = Point(pasteX, pasteY); 
     3438                    Prop pprop; 
     3439                    pprop = op.pbox.props.findProp("left"); 
     3440                    if(pprop) 
     3441                        pprop.value = std.string.toString(pasteX); 
     3442                    pprop = op.pbox.props.findProp("top"); 
     3443                    if(pprop) 
     3444                        pprop.value = std.string.toString(pasteY); 
    32113445                } 
    32123446                 
    3213                 if(++postries < 32) 
    3214                     goto trythispos; 
    3215             } 
    3216             if(nc.left != pasteX || nc.top != pasteY) 
    3217             { 
    3218                 //nc.location = Point(pasteX, pasteY); 
    3219                 Prop pprop; 
    3220                 pprop = op.pbox.props.findProp("left"); 
    3221                 if(pprop) 
    3222                     pprop.value = std.string.toString(pasteX); 
    3223                 pprop = op.pbox.props.findProp("top"); 
    3224                 if(pprop) 
    3225                     pprop.value = std.string.toString(pasteY); 
    3226             } 
    3227              
    3228             IdentProp idprop = cast(IdentProp)op.pbox.props.findProp(PropCollection.OBJECT_NAME_PROP_NAME); 
    3229             if(idprop) 
    3230             { 
    3231                 if(!isValidIdentifier(fcname) || idprop.isIdentInUse(fcname)) 
    3232                     fcname = op.idctrl.getUniqueName(); 
     3447                IdentProp idprop = cast(IdentProp)op.pbox.props.findProp(PropCollection.OBJECT_NAME_PROP_NAME); 
     3448                if(idprop) 
     3449                { 
     3450                    if(!isValidIdentifier(fcname) || idprop.isIdentInUse(fcname)) 
     3451                        fcname = op.idctrl.getUniqueName(); 
     3452                     
     3453                    idprop.value = fcname; 
     3454                } 
    32333455                 
    3234                 idprop.value = fcname; 
    3235             } 
    3236              
     3456                nc.visible = true; 
     3457                version(NOFOCUSDESIGNITEM) 
     3458                { 
     3459                } 
     3460                else 
     3461                { 
     3462                    nc.focus(); 
     3463                } 
     3464                numpasted++; 
     3465                dControlUpdateSelect(op.idctrl, true, numpasted == 1); 
     3466            } 
     3467        } 
     3468        if(numpasted) 
     3469        { 
    32373470            op.onEnd(); 
    3238             nc.visible = true; 
    3239             version(NOFOCUSDESIGNITEM) 
    3240             { 
    3241             } 
    3242             else 
    3243             { 
    3244                 nc.focus(); 
    3245             } 
    3246             dControlUpdateSelect(op.idctrl, true); 
    3247              
    32483471            updateVariableNames(this); 
    32493472            regenDesignSource(this); 
    3250              
    32513473            return true; 
    32523474        } 
     3475        return false; 
    32533476    } 
    32543477     
     
    32563479    private void menu_editDelete() 
    32573480    { 
    3258         IDesignControlItem selItem; 
    3259         selItem = getSingleSelItem(); 
    3260         if(selItem) 
    3261         { 
    3262             doDelSelItem(selItem); 
    3263         } 
     3481        doSelItemsDelete(); 
    32643482    } 
    32653483     
     
    48095027        auto tlen = statusBox.textLength; 
    48105028         
    4811         if(tlen > 1024 * 2) 
     5029        //if(tlen > 1024 * 2) 
     5030        if(tlen > 1024 * 8) 
    48125031        { 
    48135032            try 
     
    48235042         
    48245043        if(tlen) 
    4825             statusBox.appendText(\r\n); 
     5044            statusBox.appendText("\r\n"); 
    48265045        statusBox.selectedText = s; 
    48275046    } 
     
    48395058        statusBox.clear(); 
    48405059    } 
     5060    _morestatus = null; 
    48415061} 
    48425062 
     
    48455065{ 
    48465066    status("Error: " ~ errmsg); 
     5067} 
     5068 
     5069 
     5070private string[] _morestatus; 
     5071private TextBox _morestatusview = null; 
     5072private int _morestatusviewidx = -1; 
     5073 
     5074void moreStatusStart() 
     5075{ 
     5076    _morestatus ~= ""; 
     5077    if(_morestatus.length > 1) 
     5078        status("    (double-click for more) " ~ std.string.toString(_morestatus.length)); 
     5079    else 
     5080        status("    (double-click for more)"); 
     5081} 
     5082 
     5083void moreStatus(string s) 
     5084{ 
     5085    if(_morestatus.length) 
     5086    { 
     5087        if(_morestatus[$ - 1].length) 
     5088        { 
     5089            _morestatus[$ - 1] ~= "\r\n"; 
     5090            if(_morestatusview !is null && _morestatusviewidx == _morestatus.length - 1) 
     5091                _morestatusview.appendText("\r\n"); 
     5092        } 
     5093        _morestatus[$ - 1] ~= s; 
     5094        if(_morestatusview !is null && _morestatusviewidx == _morestatus.length - 1) 
     5095            _morestatusview.appendText(s); 
     5096    } 
     5097} 
     5098 
     5099private struct _morestatusform_info 
     5100{ 
     5101    void _morestatusform_closed(Object sender, EventArgs ea) 
     5102    { 
     5103        _morestatusview = null; 
     5104        _morestatusviewidx = -1; 
     5105    } 
     5106} 
     5107private _morestatusform_info i_morestatusform_info; 
     5108 
     5109void showMoreStatus(int idx) 
     5110{ 
     5111    _morestatusviewidx = idx; 
     5112    if(_morestatusview !is null) 
     5113    { 
     5114        _morestatusview.focus(); 
     5115    } 
     5116    else 
     5117    { 
     5118        Form f = new Form(); 
     5119        f.closed ~= &i_morestatusform_info._morestatusform_closed; 
     5120        f.font = new Font("Courier New", 11); 
     5121        f.size = Size(450, 340); 
     5122        f.text = "More Status"; 
     5123        f.showInTaskbar = false; 
     5124        f.startPosition = FormStartPosition.CENTER_PARENT; 
     5125        f.owner = mainForm; 
     5126        _morestatusview = new TextBox(); 
     5127        _morestatusview.scrollBars = ScrollBars.VERTICAL; 
     5128        _morestatusview.multiline = true; 
     5129        _morestatusview.readOnly = true; 
     5130        _morestatusview.dock = DockStyle.FILL; 
     5131        _morestatusview.parent = f; 
     5132        f.show(); 
     5133    } 
     5134    _morestatusview.text = _morestatus[idx]; 
     5135} 
     5136 
     5137bool doubleclickedStatusMoreStatus(string ln) 
     5138{ 
     5139    if(-1 != std.string.find(ln, "(double-click for more)")) 
     5140    { 
     5141        string snum = std.string.strip(ln[std.string.rfind(ln, ')') + 1 .. $]); 
     5142        ushort idx = 0; 
     5143        if(snum.length) 
     5144        { 
     5145            try 
     5146            { 
     5147                idx = std.conv.toUshort(snum) - 1; 
     5148            } 
     5149            catch 
     5150            { 
     5151                return false; 
     5152            } 
     5153        } 
     5154        if(idx >= _morestatus.length) 
     5155            return false; 
     5156        showMoreStatus(idx); 
     5157        return true; 
     5158    } 
     5159    return false; 
    48475160} 
    48485161 
     
    53625675            parent = propHolder; 
    53635676             
     5677            alignment = TabberAlignment.BOTTOM; 
     5678             
    53645679            //addTab(new Tab("Entice")); // Testing. 
    53655680        } 
     
    54085723                 
    54095724                doubleClick ~= &statusBox_doubleClick; 
     5725                //mouseUp ~= &statusBox_mouseUp; 
    54105726            } 
    54115727        } 
     
    60076323        addShortcut(Keys.SHIFT | Keys.F2, &shortcut_shiftF2); 
    60086324        addShortcut(Keys.CONTROL | Keys.F2, &shortcut_ctrlF2); 
     6325         
     6326        addShortcut(Keys.CONTROL | Keys.OEM_CLOSE_BRACKETS, &shortcut_ctrlRightBracket); 
     6327         
    60096328    } 
    60106329     
     
    60126331    void loadMainFormInitValues() 
    60136332    { 
     6333        auto rkey = getRkey(); 
    60146334        int xi; 
    6015         auto rkey = getRkey(); 
    6016          
    6017         // Set the window bounds. Try to load from registry. 
    6018         xi = rkey.getEntryInt("X", -1); 
    6019         if(-1 == xi) 
    6020         { 
    6021             // Bounds not in registry. 
    6022              
    6023             /+ 
    6024             // Let windows set it. 
    6025             startPosition = FormStartPosition.WINDOWS_DEFAULT_BOUNDS; 
    6026             +/ 
    6027              
    6028             // Set the bounds to something a bit bigger. 
    6029             //startPosition = FormStartPosition.CENTER_SCREEN; 
    6030             RECT workArea; 
    6031             if(SystemParametersInfoA(SPI_GETWORKAREA, 0, &workArea, 0)) 
    6032             { 
     6335         
     6336        { 
     6337            startPosition = FormStartPosition.MANUAL; 
     6338            // Set the window bounds. Try to load from config. 
     6339            xi = rkey.getEntryInt("X", -111111111); 
     6340            bool needdefbounds = true; 
     6341            Rect workArea; 
     6342            if(-111111111 == xi) 
     6343            { 
     6344                workArea = Screen.primaryScreen.workingArea; 
     6345            } 
     6346            else 
     6347            { 
     6348                // Bounds in config. 
     6349                { 
     6350                    int cX, cY, cDX, cDY; 
     6351                    cX = xi; 
     6352                    cY = rkey.getEntryInt("Y", -1); 
     6353                    cDX = rkey.getEntryInt("DX", -1); 
     6354                    cDY = rkey.getEntryInt("DY", -1); 
     6355                    bounds = Rect(cX, cY, cDX, cDY); 
     6356                } 
     6357                workArea = Screen.fromRectangle(bounds).workingArea; 
     6358                if(workArea.contains(bounds)) 
     6359                { 
     6360                    needdefbounds = false; 
     6361                } 
     6362            } 
     6363            if(needdefbounds) 
     6364            { 
     6365                assert(workArea.width && workArea.height); 
    60336366                int sw, sh; 
    60346367                 
    6035                 sw = workArea.right - workArea.left
    6036                 sh = workArea.bottom - workArea.top
     6368                sw = workArea.right - workArea.x
     6369                sh = workArea.bottom - workArea.y
    60376370                 
    6038                 /+if(sw <= 800 || sh <= 600) 
    6039                 { 
    6040                     startPosition = FormStartPosition.WINDOWS_DEFAULT_BOUNDS; 
    6041                 } 
    6042                 else+/ 
    6043                 { 
    6044                     //width = sw - sw / 8; // Proportional gap. 
    6045                     width = sw - sh / 8; // Same gap. 
    6046                     height = sh - sh / 8; 
    6047                 } 
     6371                //width = sw - sw / 8; // Proportional gap. 
     6372                width = sw - sh / 8; // Same gap. 
     6373                height = sh - sh / 8; 
    60486374                 
    60496375                centerToScreen(); 
    60506376            } 
    6051             else 
    6052             { 
    6053                 //startPosition = FormStartPosition.WINDOWS_DEFAULT_BOUNDS; 
    6054             } 
    6055         } 
    6056         else 
    6057         { 
    6058             startPosition = FormStartPosition.MANUAL; 
    6059              
    6060             left = xi; 
    6061             xi = rkey.getEntryInt("Y", -1); 
    6062             if(-1 != xi) 
    6063                 top = xi; 
    6064             xi = rkey.getEntryInt("DX", -1); 
    6065             if(-1 != xi && xi > width) 
    6066                 width = xi; 
    6067             xi = rkey.getEntryInt("DY", -1); 
    6068             if(-1 != xi && xi > height) 
    6069                 height = xi; 
    60706377        } 
    60716378         
     
    64526759     
    64536760    static ContextMenu cmTabDown; 
    6454     static MenuItem tmdExtendedPropsMenu, tmdSaveMenu, tmdSaveAsMenu; 
     6761    static MenuItem tmdExtendedPropsMenu, tmdSaveMenu, tmdSaveAsMenu, 
     6762        tmdDetachMenu; 
    64556763     
    64566764     
     
    64586766    { 
    64596767        closeCurrent(); 
     6768    } 
     6769     
     6770     
     6771    private void tmdDetachMenu_click(Object sender, EventArgs ea) 
     6772    { 
     6773        int selidx = tabs.selectedIndex; 
     6774        if(-1 != selidx) 
     6775            tabs.detachTab(selidx); 
    64606776    } 
    64616777     
     
    65026818                cmTabDown.menuItems.add(mi); 
    65036819                 
     6820                /+ 
     6821                with(tmdDetachMenu = new MenuItem()) 
     6822                { 
     6823                    text = "&Detach"; 
     6824                    click ~= &tmdDetachMenu_click; 
     6825                } 
     6826                cmTabDown.menuItems.add(tmdDetachMenu); 
     6827                +/ 
     6828                 
    65046829                with(mi = new MenuItem()) 
    65056830                { 
     
    65556880                byes = ent.canSave; 
    65566881             
     6882            if(tmdDetachMenu) 
     6883                tmdDetachMenu.enabled = et && (et.flags & ETabFlags.ALLOW_DETACH); 
    65576884            tmdSaveMenu.enabled = byes; 
    65586885            tmdSaveAsMenu.enabled = byes; 
    65596886             
    65606887            cmTabDown.show(tabs, tabs.pointToScreen(Point(ea.x, ea.y))); 
     6888        } 
     6889        else if(ea.button == MouseButtons.MIDDLE) 
     6890        { 
     6891            assert(ea.tab is getCurrentTab()); 
     6892             
     6893            closeCurrent(); 
    65616894        } 
    65626895    } 
     
    67317064     
    67327065     
     7066    bool _showingopts = false; 
     7067     
    67337068    // -tabshow- is the GID of the tab to show, or the index of the tab to show. 
    6734     final void n(uint32_t tabshow = 0) 
    6735     { 
     7069    final void n(uint32_t tabshow = 0, void delegate(DdOptionsForm) optsReady = null) 
     7070    { 
     7071        if(_showingopts) 
     7072            return; 
    67367073        DdOptionsForm foo; 
    67377074        with(foo = new DdOptionsForm) 
    67387075        { 
     7076            if(optsReady) 
     7077                foo.optionsReady = optsReady; 
    67397078            icon = this.icon; 
    67407079            tabFirstShow = tabshow; 
     7080            _showingopts = true; 
    67417081            showDialog(this); 
     7082            _showingopts = false; 
    67427083            dispose(); 
    67437084        } 
     
    67677108        foreach(inout ApiEntry onae; *an) 
    67687109        { 
     7110            if(onae.flags & ApiFlags.UNDOCUMENTED) // Skip undocumented ones. 
     7111                continue; 
     7112            if(onae.flags & ApiFlags.PRIVATE) // Skip private ones. 
     7113                continue; 
    67697114            if(onae.flags & ApiFlags.PACKAGE) // Skip package ones in this view (e.g. ControlSuperClass). 
    67707115                continue; 
     
    71737518     
    71747519     
     7520    private void shortcut_ctrlRightBracket(Object sender, FormShortcutEventArgs ea) 
     7521    { 
     7522        EditorTab etab; 
     7523        etab = cast(EditorTab)getCurrentTab(); 
     7524        if(etab) 
     7525        { 
     7526            int istart, iend; 
     7527            if(etab.asci.findBraceMatch(istart, iend)) 
     7528            { 
     7529                etab.asci.sendEditor(SCI_GOTOPOS, iend); 
     7530            } 
     7531        } 
     7532    } 
     7533     
     7534     
     7535    private void shortcut_F5(Object sender, FormShortcutEventArgs ea) 
     7536    { 
     7537        EditorTab etab; 
     7538        etab = cast(EditorTab)getCurrentTab(); 
     7539        if(etab) 
     7540        { 
     7541            msgBox("Debugger not enabled.\r\n" 
     7542                "Proceeding to compile and run without debugger...\r\n" 
     7543                "Use Ctrl+F5 next time to avoid attempting to use a debugger.\r\n"); 
     7544            shortcut_ctrlF5(sender, ea); 
     7545        } 
     7546    } 
     7547     
     7548     
     7549    private void shortcut_ctrlF5(Object sender, FormShortcutEventArgs ea) 
     7550    { 
     7551        // Compile and run without debugging... 
     7552         
     7553        EditorTab etab; 
     7554        etab = cast(EditorTab)getCurrentTab(); 
     7555        if(etab) 
     7556        { 
     7557            string fp = etab.entity.filePath; 
     7558            if(fp.length > 2 
     7559                && ".d" == fp[$ - 2 .. $]) 
     7560            { 
     7561                clearStatus(); 
     7562                 
     7563                try 
     7564                { 
     7565                    ensureCompiler(); 
     7566                     
     7567                    //status("Building..."); 
     7568                    status("Building current file without project..."); 
     7569                     
     7570                    //Process cproc = callCompilerWithSc("-c -o- -deps=con " ~ fp); 
     7571                    Process cproc = callCompilerWithSc(fp); 
     7572                    int nlines = 0; 
     7573                    while(!cproc.stdout.eof()) 
     7574                    { 
     7575                        string ln = std.string.strip(cproc.stdout.readLine()); 
     7576                        if(ln.length) 
     7577                        { 
     7578                            if(nlines < 10) 
     7579                            { 
     7580                                status(ln); 
     7581                            } 
     7582                            else 
     7583                            { 
     7584                                if(10 == nlines) 
     7585                                    moreStatusStart(); 
     7586                                moreStatus(ln); 
     7587                            } 
     7588                            nlines++; 
     7589                        } 
     7590                    } 
     7591                    cproc.waitForExit(); 
     7592                    cproc.stdout.close(); 
     7593                    { 
     7594                        int status = cproc.exitCode; 
     7595                        if(0 != status) 
     7596                            throw new Exception("Returned status code " 
     7597                                ~ std.string.toString(status)); 
     7598                    } 
     7599                    cproc.close(); 
     7600                    status("Compiled successfully"); 
     7601                } 
     7602                catch(Exception e) 
     7603                { 
     7604                    status("Compile error: " ~ e.toString()); 
     7605                } 
     7606                 
     7607                doDelayGc(); 
     7608                 
     7609            } 
     7610        } 
     7611    } 
     7612     
     7613     
    71757614    private void shortcut_ctrlSpace(Object sender, FormShortcutEventArgs ea) 
    71767615    { 
     
    73527791                for(;;) 
    73537792                { 
    7354                     //if(!dfl.utf.getMessage(&msg, null, 0, 0)) // Makes it not work right.. 
     7793                    //if(!dfl.internal.utf.getMessage(&msg, null, 0, 0)) // Makes it not work right.. 
    73557794                    if(!GetMessageA(&msg, null, 0, 0)) 
    73567795                        break; 
     
    73597798                    { 
    73607799                        TranslateMessage(&msg); 
    7361                         dfl.utf.dispatchMessage(&msg); 
     7800                        dfl.internal.utf.dispatchMessage(&msg); 
    73627801                        break; 
    73637802                    } 
     
    74107849                        default: process_msg: 
    74117850                            //TranslateMessage(&msg); // No need. 
    7412                             dfl.utf.dispatchMessage(&msg); 
     7851                            dfl.internal.utf.dispatchMessage(&msg); 
    74137852                    } 
    74147853                } 
     
    75237962                //msgBox(`"` ~ dclickedLineString ~ `"`, "dclickedLineString"); 
    75247963                 
    7525                 firePluginEvent!(PluginEventProc_str_int, PluginEventIgnoreResult, char*, int) 
    7526                     (PluginEventType.OUTPUTDCLICK, dclickedLineString.ptr, dclickedLineString.length); 
    7527             } 
    7528         } 
    7529     } 
     7964                if(!doubleclickedStatusOpenFile(dclickedLineString) 
     7965                    && !doubleclickedStatusMoreStatus(dclickedLineString)) 
     7966                { 
     7967                    firePluginEvent!(PluginEventProc_str_int, PluginEventIgnoreResult, char*, int) 
     7968                        (PluginEventType.OUTPUTDCLICK, dclickedLineString.ptr, dclickedLineString.length); 
     7969                } 
     7970            } 
     7971        } 
     7972    } 
     7973     
     7974     
     7975    /+ 
     7976    private void statusBox_mouseUp(Control sender, MouseEventArgs ea) 
     7977    { 
     7978        if(ea.button == MouseButtons.LEFT) 
     7979        { 
     7980            if(statusBox.selectionLength < 1) 
     7981            { 
     7982                int selstart = statusBox.selectionStart; 
     7983                if(selstart >= 0) 
     7984                { 
     7985                    auto line0idx = statusBox.getLineFromCharIndex(selstart); // 0 based. 
     7986                    auto lines = statusBox.lines; 
     7987                    if(line0idx < lines.length) 
     7988                    { 
     7989                        auto lineString = lines[line0idx]; 
     7990                        statusBox.select(statusBox.getFirstCharIndexFromLine(line0idx), 
     7991                            lineString.length); 
     7992                    } 
     7993                } 
     7994            } 
     7995        } 
     7996    } 
     7997    +/ 
    75307998     
    75317999     
     
    78248292            if(filepath.length) 
    78258293            { 
    7826                 filepath = dfl.utf.getFullPathName(filepath); 
     8294                filepath = dfl.internal.utf.getFullPathName(filepath); 
    78278295                 
    78288296                if(!std.string.icmp(ent.filePath, filepath)) // Required with below already-open check. 
     
    79228390         
    79238391        curi = tabs.selectedIndex; 
     8392        if(-1 == curi) 
     8393        { 
     8394            if(tabs.tabs.length) 
     8395            { 
     8396                //tabs.attachTab(0); 
     8397                curi = 0; 
     8398            } 
     8399        } 
    79248400        if(-1 != curi) 
    79258401        { 
     
    79658441    final void doOpen(char[] filepath, bool wantEditor = false) 
    79668442    { 
    7967         filepath = dfl.utf.getFullPathName(filepath); 
     8443        filepath = dfl.internal.utf.getFullPathName(filepath); 
    79688444         
    79698445        if(!canAddEntity()) 
     
    81988674                    if(proj) // Should always be true. 
    81998675                    { 
    8200                         proj.ensureFileAdded(filepath); 
     8676                        proj.fileOpened(filepath); 
    82018677                    } 
    82028678                     
     
    83158791    { 
    83168792        if(!canAddEntity()) 
    8317             return false; 
     8793        //  return false; 
     8794            return; 
    83188795         
    83198796        char[] itemtype; 
     
    86249101            { 
    86259102                Application.doEvents(); // ? 
    8626                 proj.ensureFileAdded(filepath); 
     9103                proj.fileOpened(filepath); 
    86279104            } 
    86289105             
     
    86589135    { 
    86599136        if(!canAddEntity()) 
    8660             return false; 
     9137        //  return false; 
     9138            return; 
    86619139         
    86629140        auto ent = new Entity(Entity.UNTITLED); 
     
    88079285     
    88089286     
    8809     package static void tellPluginsLoaded() 
    8810     { 
    8811         if(anyPlugins()) 
    8812         { 
    8813             //delayInvoke(function(Control ctrl, size_t[] params) { signalPluginsLoaded(); }); 
    8814             signalPluginsLoaded(); 
     9287    // Calls the plugins' "loaded"! 
     9288    // This handles 'default' plugins, etc. 
     9289    // and conflicting features. 
     9290    package static void finishPluginsLoaded() 
     9291    { 
     9292        //if(anyPlugins()) // Always going to be some due to built-in ones. 
     9293        { 
     9294            //signalPluginsLoaded(); 
     9295            _handlePluginConflict(EnticePluginFlags.PLUGIN_PROJECT_LIST, "project listing (project management)"); 
     9296            _handlePluginConflict(EnticePluginFlags.PLUGIN_PROJECT_COMPILE, "project compile (project management)"); 
     9297            _handlePluginConflict(EnticePluginFlags.PLUGIN_CODECOMPLETION, "source code autocompletion"); 
     9298            _handlePluginConflict(EnticePluginFlags.PLUGIN_CODELAYOUTTAB, "code layout (code overviews)"); 
     9299            foreach(Plugin plug; plugins.plugins) 
     9300            { 
     9301                signalOnePluginLoaded(plug); 
     9302            } 
     9303        } 
     9304    } 
     9305
     9306 
     9307 
     9308private void _handlePluginConflict(uint checkflag, string type) 
     9309
     9310    Plugin[] plugs_lo, plugs_med, plugs_hi; // High is non-default normal. 
     9311    foreach(Plugin plug; plugins.plugins) 
     9312    { 
     9313        if(plug.flags & checkflag) 
     9314        { 
     9315            if(plug.flags & EnticePluginFlags.PLUGIN_DEFAULT) 
     9316                plugs_lo ~= plug; 
     9317            else if(plug.flags & EnticePluginFlags.PLUGIN_DEFAULT2) 
     9318                plugs_med ~= plug; 
     9319            else 
     9320                plugs_hi ~= plug; 
     9321        } 
     9322    } 
     9323    if(plugs_hi.length > 1 
     9324        || (plugs_hi.length == 0 && plugs_med.length > 1) 
     9325        || (plugs_hi.length == 0 && plugs_med.length == 0 && plugs_lo.length > 1) 
     9326        ) 
     9327    { 
     9328        // Conflict. 
     9329        scope pf = (new PromptForm("Plugin Conflict")) 
     9330            .addLabel("Conflicts found while loading plugin of type " ~ type).ret() 
     9331            .addLabel("Please resolve the conflict by selecting which plugin to load:").ret() 
     9332            ; 
     9333        foreach(Plugin plug; plugs_hi ~ plugs_med ~ plugs_lo) 
     9334        { 
     9335            pf.addRadioButton(plug.name, plug.name ~ "  -  " ~ plug.desc, false).ret(); 
     9336        } 
     9337        pf.validate( 
     9338            (PromptForm _pf) 
     9339            { 
     9340                int numchecked = 0; 
     9341                foreach(Plugin plug; plugs_hi ~ plugs_med ~ plugs_lo) 
     9342                { 
     9343                    RadioButton ctrl = cast(RadioButton)_pf.get(plug.name); 
     9344                    if(ctrl && ctrl.checked) 
     9345                    { 
     9346                        //whichctrl = ctrl; 
     9347                        numchecked++; 
     9348                    } 
     9349                } 
     9350                if(numchecked != 1) 
     9351                { 
     9352                    msgBox(_pf, "Please select which plugin to load", _pf.text); 
     9353                    return false; 
     9354                } 
     9355                return true; 
     9356            }); 
     9357        string which = null; 
     9358        bool ok = DialogResult.OK == pf.showDialog(); 
     9359        foreach(Plugin plug; plugs_hi ~ plugs_med ~ plugs_lo) 
     9360        { 
     9361            RadioButton ctrl = cast(RadioButton)pf.get(plug.name); 
     9362            if(ok && ctrl && ctrl.checked) 
     9363            { 
     9364                continue; 
     9365            } 
     9366            ddUnloadPlugin(plug); 
     9367            if(ok) // Stop the others from loading in the future. 
     9368                setShouldLoadPlugin(plug.fname, 0); 
     9369        } 
     9370        pf.dispose(); 
     9371    } 
     9372    else 
     9373    { 
     9374        // No conflict. 
     9375        if(1 == plugs_hi.length) 
     9376        { 
     9377            foreach(Plugin plug; plugs_lo) 
     9378            { 
     9379                ddUnloadPlugin(plug); 
     9380            } 
     9381            foreach(Plugin plug; plugs_med) 
     9382            { 
     9383                ddUnloadPlugin(plug); 
     9384            } 
     9385        } 
     9386        else if(1 == plugs_med.length) 
     9387        { 
     9388            foreach(Plugin plug; plugs_lo) 
     9389            { 
     9390                ddUnloadPlugin(plug); 
     9391            } 
     9392            foreach(Plugin plug; plugs_hi) 
     9393            { 
     9394                ddUnloadPlugin(plug); 
     9395            } 
     9396        } 
     9397        else if(1 == plugs_lo.length) 
     9398        { 
     9399            foreach(Plugin plug; plugs_med) 
     9400            { 
     9401                ddUnloadPlugin(plug); 
     9402            } 
     9403            foreach(Plugin plug; plugs_hi) 
     9404            { 
     9405                ddUnloadPlugin(plug); 
     9406            } 
    88159407        } 
    88169408    } 
     
    90889680    +/ 
    90899681    loadExtraOptions(rkeysub); // Might be null. 
     9682     
     9683    rkeysub = rkey.openSubGroup("Compiler"); 
     9684    loadCompileSettings(rkeysub); // Might be null. 
    90909685} 
    90919686 
     
    91339728    } 
    91349729} 
    9135  
    9136  
    9137 /+ // This mess was replaced. 
    9138 char[][] notloadedplugins; // Just file names. Strings end up null if the plugins end up getting loaded. 
    9139 char[][] notloadedpluginpaths; // Full paths for above; indices correspond. Strings end up null if the plugins end up getting loaded. 
    9140 char[][] loadeddapiplugins; // Just file names. 
    9141 char[][] unloadingplugins; // Plugins scheduled for unloading via user in options. 
    9142 // ... loaded plugins are in plugins. 
    9143  
    9144  
    9145 bool isPluginUnloading(char[] fname) 
    9146 { 
    9147     foreach(un; unloadingplugins) 
    9148     { 
    9149         if(!std.string.icmp(un, fname)) 
    9150             return true; 
    9151     } 
    9152     return false; 
    9153 } 
    9154  
    9155  
    9156 void setPluginUnloading(char[] fname, bool byes = true) 
    9157 { 
    9158     foreach(idx, un; unloadingplugins) 
    9159     { 
    9160         if(!std.string.icmp(un, fname)) 
    9161         { 
    9162             if(!byes) 
    9163             { 
    9164                 if(!idx) 
    9165                     unloadingplugins = unloadingplugins[1 .. $]; 
    9166                 else if(idx == unloadingplugins.length - 1) 
    9167                     unloadingplugins = unloadingplugins[1 .. idx]; 
    9168                 else 
    9169                     unloadingplugins = unloadingplugins[0 .. idx] ~ unloadingplugins[idx + 1 .. $]; 
    9170             } 
    9171             return; 
    9172         } 
    9173     } 
    9174      
    9175     if(byes) 
    9176         unloadingplugins ~= fname; 
    9177 } 
    9178  
    9179  
    9180 void loadPlugins() 
    9181 { 
    9182     assert(!notloadedplugins.length); 
    9183     assert(!notloadedpluginpaths.length); 
    9184     assert(!loadeddapiplugins.length); 
    9185      
    9186     DWORD numPluginThreads = 1; 
    9187     int xi; 
    9188      
    9189     xi = getRkey().getEntryInt("PluginThreads", -1); 
    9190     if(-1 != xi) 
    9191     { 
    9192         numPluginThreads = xi; 
    9193         if(numPluginThreads > 8) 
    9194             numPluginThreads = 8; 
    9195     } 
    9196      
    9197     char[] plugindir; 
    9198     char[][] dapis; // dapi files in plugin dir. 
    9199     char[][] dlls; // dll files in plugin dir. 
    9200     auto pigrp = getRkey().openSubGroup("Load"); // Plugin info config. Might be null! In this case, plShouldLoadPlugin always returns 1. 
    9201      
    9202     plugindir = pathJoinAbsolute(Application.startupPath, "Plugins"); 
    9203      
    9204     // Returns 1 if yes, 0 if no, or 2 only if version permits it (if not, be silent); default is 1; returns negative for error. 
    9205     int plShouldLoadPlugin(char[] name) 
    9206     { 
    9207         if(!pigrp) 
    9208             return 1; 
    9209         return pigrp.getEntryInt("P:" ~ name, 1); 
    9210     } 
    9211      
    9212     void plSetShouldLoadPlugin(char[] name, int should) 
    9213     { 
    9214         if(!pigrp) 
    9215             pigrp = getRkey().createSubGroup("Load"); 
    9216         pigrp.setEntryInt("P:" ~ name, should); 
    9217     } 
    9218      
    9219     listdir(plugindir, 
    9220         (DirEntry* de) 
    9221         { 
    9222             if(de.isfile()) 
    9223             { 
    9224                 char[] ext, fname; 
    9225                 ext = std.path.getExt(de.name); 
    9226                 fname = std.path.getBaseName(de.name); 
    9227                  
    9228                 if(!std.string.icmp("dapi", ext)) 
    9229                 { 
    9230                     if(plShouldLoadPlugin(fname) > 0) 
    9231                     { 
    9232                         loadeddapiplugins ~= fname.dup; // Need dup? 
    9233                         //dapis ~= pathJoinAbsolute(plugindir, de.name); 
    9234                         dapis ~= pathJoinAbsolute(plugindir, fname); 
    9235                     } 
    9236                     else 
    9237                     { 
    9238                         //notloadedpluginpaths ~= pathJoinAbsolute(plugindir, de.name); 
    9239                         notloadedpluginpaths ~= pathJoinAbsolute(plugindir, fname); 
    9240                          
    9241                         notloadedplugins ~= fname.dup; // Need dup? 
    9242                     } 
    9243                 } 
    9244                 else if(!std.string.icmp("dll", ext)) 
    9245                 { 
    9246                     if(plShouldLoadPlugin(fname) > 0) 
    9247                     { 
    9248                         //dlls ~= pathJoinAbsolute(plugindir, de.name); 
    9249                         dlls ~= pathJoinAbsolute(plugindir, fname); 
    9250                     } 
    9251                     else 
    9252                     { 
    9253                         //notloadedpluginpaths ~= pathJoinAbsolute(plugindir, de.name); 
    9254                         notloadedpluginpaths ~= pathJoinAbsolute(plugindir, fname); 
    9255                          
    9256                         notloadedplugins ~= fname.dup; // Need dup? 
    9257                     } 
    9258                 } 
    9259             } 
    9260             return true; // Continue. 
    9261         }); 
    9262      
    9263     // To-do: repeat the above for files in ApplicationData/Entice/Plugins 
    9264      
    9265     try 
    9266     { 
    9267         if(dapis.length) 
    9268         { 
    9269             if(!numPluginThreads) 
    9270             { 
    9271                 apiinfo.setUnloaded(); 
    9272                 _loadDapiFiles(dapis); 
    9273                 apiinfo.setLoadedOne(); 
    9274             } 
    9275             else 
    9276             { 
    9277                 Thread thd; 
    9278                 apiinfo.setUnloaded(1); // 1 thread for now. 
    9279                 thd = new _DoDapiThread(dapis); 
    9280                 dapis = null; 
    9281                 thd.start(); 
    9282             } 
    9283         } 
    9284         else 
    9285         { 
    9286             apiinfo.setUnloaded(); 
    9287             apiinfo.setLoadedOne(); 
    9288         } 
    9289     } 
    9290     catch(Object o) 
    9291     { 
    9292         writeErrorLog(o); 
    9293          
    9294         dapiError(o); 
    9295     } 
    9296      
    9297     if(dlls.length) 
    9298     { 
    9299         try 
    9300         { 
    9301             char[][] dllerrs; 
    9302             Plugin plug; 
    9303             char[] emsg; 
    9304              
    9305             foreach(char[] dllf; dlls) 
    9306             { 
    9307                 int errnum; 
    9308                 emsg = loadDllPlugin(dllf, plug, true, errnum); 
    9309                 if(emsg.length) 
    9310                 { 
    9311                     char[] plfn = std.path.getBaseName(dllf); 
    9312                      
    9313                     notloadedpluginpaths ~= dllf; 
    9314                      
    9315                     notloadedplugins ~= plfn; 
    9316                      
    9317                     if(8 == errnum) // Version mismatch. 
    9318                     { 
    9319                         if(2 == plShouldLoadPlugin(plfn)) // Version mismatch silenced previously. 
    9320                             continue; 
    9321                         msgBox(emsg, "Plugin: " ~ plfn, MsgBoxButtons.OK, MsgBoxIcon.ASTERISK); 
    9322                         plSetShouldLoadPlugin(plfn, 2); // Silence for next time. 
    9323                     } 
    9324                     else 
    9325                     { 
    9326                         dllerrs ~= emsg; 
    9327                     } 
    9328                 } 
    9329                 else 
    9330                 { 
    9331                     if(plug) 
    9332                         registerPlugin(plug); 
    9333                 } 
    9334             } 
    9335              
    9336             if(dllerrs.length) 
    9337             { 
    9338                 if(1 == dllerrs.length) 
    9339                     emsg = "1 error"; 
    9340                 else 
    9341                     emsg = std.string.format("%d errors", dllerrs.length); 
    9342                 emsg ~= " occured while loading plugins:"; 
    9343                 foreach(size_t idxmsg, char[] smsg; dllerrs) 
    9344                 { 
    9345                     emsg ~= "\r\n   "; 
    9346                     emsg ~= smsg; 
    9347                 } 
    9348                 throw new Exception(emsg); 
    9349             } 
    9350         } 
    9351         catch(Object e) 
    9352         { 
    9353             writeErrorLog(e); 
    9354              
    9355             Application.onThreadException(e); 
    9356             Application.onThreadException(new Exception("Unable to finish loading plugins; functionality may be limited until this is remedied")); 
    9357         } 
    9358     } 
    9359 } 
    9360 +/ 
    93619730 
    93629731 
     
    93699738    LOADED = 0x2, 
    93709739    UNLOADING = 0x4, 
     9740    BUILTIN = 0x8, 
    93719741} 
    93729742 
     
    93829752    char[] fullpath() // getter 
    93839753    { 
     9754        //assert(_fullpath !is null, "DdPluginInfo._fullpath is null"); 
    93849755        return _fullpath[0 .. _fullpathlen]; 
    93859756    } 
     
    93899760    char[] fname() // getter 
    93909761    { 
    9391         return _fullpath[_fullpathlen - _nameoffsetr .. _fullpathlen]; 
     9762        return fullpath[$ - _nameoffsetr .. $]; 
    93929763    } 
    93939764     
     
    94209791 
    94219792 
     9793void ddUnloadPlugin(Plugin plug) 
     9794{ 
     9795    foreach(ref DdPluginInfo ddpi; ddplugins) 
     9796    { 
     9797        if(0 == std.string.icmp(ddpi.fname, plug.fname)) 
     9798        { 
     9799            if(ddpi.flags & DDPI.LOADED) 
     9800            { 
     9801                ddpi.flags |= DDPI.NOTLOADING; 
     9802            } 
     9803            else 
     9804            { 
     9805                ddpi.flags |= DDPI.UNLOADING; 
     9806            } 
     9807            ddpi.flags &= ~DDPI.LOADED; 
     9808            break; 
     9809        } 
     9810    } 
     9811    plug.dispose(); 
     9812    plugins.plugins.remove(plug.pluginid); 
     9813} 
     9814 
     9815 
    94229816int findPluginInfo(char[] fname, DdPluginInfo* info = null) 
    94239817{ 
     
    94409834    char[] plugindir; 
    94419835     
     9836    if(!startlen) 
     9837    { 
     9838        // Add built-in plugins. 
     9839        { 
     9840            DdPluginInfo ddpi; 
     9841            ddpi.setFile("Projects", 0); 
     9842            ddpi.flags = DDPI.BUILTIN; 
     9843            ddplugins ~= ddpi; 
     9844            onNewPluginFound(ddplugins[$ - 1]); 
     9845        } 
     9846    } 
     9847     
    94429848    plugindir = pathJoinAbsolute(Application.startupPath, "Plugins"); 
    94439849    listdir(plugindir, 
     
    94489854                char[] ext = std.path.getExt(de.name); 
    94499855                 
    9450                 if(!std.string.icmp("dapi", ext) || !std.string.icmp("dll", ext)) 
     9856                if(!std.string.icmp("dapi", ext) || !std.string.icmp("json", ext) 
     9857                    || !std.string.icmp("dll", ext)) 
    94519858                { 
    94529859                    char[] fname = std.path.getBaseName(de.name); 
     
    95009907 
    95019908 
    9502 void loadPlugins() 
     9909class ProjectsPlugin: Plugin 
     9910
     9911    this() 
     9912    { 
     9913        name = "Projects"; 
     9914        fname = name; 
     9915        desc = "Built-in project management and compile features."; 
     9916        majorVersion = CURMAJORVERSION; 
     9917        minorVersion = CURMINORVERSION; 
     9918        flags = EnticePluginFlags.PLUGIN_DEFAULT2 
     9919            | EnticePluginFlags.PLUGIN_SAFEUNLOAD 
     9920            | EnticePluginFlags.PLUGIN_PROJECT_COMPILE 
     9921            //| EnticePluginFlags.PLUGIN_PROJECT_LIST // Not yet, heh 
     9922            ; 
     9923    } 
     9924     
     9925     
     9926     
     9927    bool addedCtrlF5 = false; 
     9928    bool addedF5 = false; 
     9929     
     9930    protected override void loaded() 
     9931    { 
     9932        super.loaded(); 
     9933         
     9934        try 
     9935        { 
     9936            mainForm.addShortcut(Keys.CONTROL | Keys.F5, &mainForm.shortcut_ctrlF5); 
     9937            addedCtrlF5 = true; 
     9938        } 
     9939        catch 
     9940        { 
     9941        } 
     9942         
     9943        try 
     9944        { 
     9945            mainForm.addShortcut(Keys.F5, &mainForm.shortcut_F5); 
     9946            addedF5 = true; 
     9947        } 
     9948        catch 
     9949        { 
     9950        } 
     9951         
     9952        //addShortcut(Keys.F7, &shortcut_ctrlF7); 
     9953         
     9954        /* 
     9955        pluginid    this plugin ID. 
     9956        name    pointer to the name displayed on the menu item, or a single dash for a menu separator. 
     9957        namelen length of bytes at name. 
     9958        menuid  menu ID unique to this plugin. Must be positive. May include menu options with eidOptions(). 
     9959        tomenuid    the parent menu to add to, -1 to remove, or one of EMENU_* constants. 
     9960        callback    called back on click: menuCallback(EnticeFunctions* efuncs, int menuid); 
     9961        */ 
     9962        //EMENU_PROJECT 
     9963        //efuncs.registerMenuItem() 
     9964         
     9965    } 
     9966     
     9967     
     9968    protected override void unloading() 
     9969    { 
     9970        if(addedCtrlF5) 
     9971        { 
     9972            addedCtrlF5 = false; 
     9973            try 
     9974            { 
     9975                mainForm.removeShortcut(Keys.CONTROL | Keys.F5); 
     9976            } 
     9977            catch 
     9978            { 
     9979            } 
     9980        } 
     9981        if(addedF5) 
     9982        { 
     9983            addedF5 = false; 
     9984            try 
     9985            { 
     9986                mainForm.removeShortcut(Keys.F5); 
     9987            } 
     9988            catch 
     9989            { 
     9990            } 
     9991        } 
     9992         
     9993        super.unloading(); 
     9994    } 
     9995     
     9996
     9997 
     9998 
     9999Plugin getBuiltinPlugin(char[] name) 
     10000
     10001    switch(name) 
     10002    { 
     10003        case "Projects": return new ProjectsPlugin(); 
     10004        default: assert(0); return null; 
     10005    } 
     10006
     10007 
     10008 
     10009// 1 if yes, 0 if no, or 2 only if version permits it 
     10010void setShouldLoadPlugin(IRGroup pigrp, char[] name, int should) 
     10011
     10012    if(!pigrp) 
     10013        pigrp = getRkey().createSubGroup("Load"); 
     10014    pigrp.setEntryInt("P:" ~ name, should); 
     10015
     10016 
     10017void setShouldLoadPlugin(char[] name, int should) 
     10018
     10019    setShouldLoadPlugin(null, name, should); 
     10020
     10021 
     10022 
     10023void setupPlugins() 
    950310024{ 
    950410025    assert(!ddplugins.length); 
     
    953910060            return pigrp.getEntryInt("P:dwt.dapi", 0); // Default for this is no-load. 
    954010061        } 
     10062        if(!std.string.icmp("dfl.dapi", name)) 
     10063        { 
     10064            if(!pigrp) 
     10065                return 0; 
     10066            // Default for this is no-load because of the new dfl.json! 
     10067            return pigrp.getEntryInt("P:dfl.dapi", 0); 
     10068        } 
     10069        /+if(!std.string.icmp("dirproj.dll", name)) 
     10070        { 
     10071            if(!pigrp) 
     10072                return 0; 
     10073            // Favor the built-in projects first. 
     10074            // Actually don't need to do this 
     10075            // because it's marked as EPF_PLUGIN_DEFAULT (last resort) 
     10076            return pigrp.getEntryInt("P:dirproj.dll", 0); 
     10077        }+/ 
    954110078         
    954210079        if(!pigrp) 
     
    954710084    void plSetShouldLoadPlugin(char[] name, int should) 
    954810085    { 
    9549         if(!pigrp) 
    9550             pigrp = getRkey().createSubGroup("Load"); 
    9551         pigrp.setEntryInt("P:" ~ name, should); 
     10086        setShouldLoadPlugin(pigrp, name, should); 
    955210087    } 
    955310088     
     
    955710092            { 
    955810093                char[] ext = std.path.getExt(ddpi.fullpath); 
    9559                 if(!std.string.icmp(ext, "dapi")) 
     10094                if(!std.string.icmp(ext, "dapi") 
     10095                    || !std.string.icmp(ext, "json")) 
    956010096                { 
    956110097                    dapis ~= ddpi.fullpath; 
     
    960210138    } 
    960310139     
    9604     //if(dlls.length) 
    960510140    { 
    960610141        try 
     
    961210147            foreach(inout DdPluginInfo ddpi; ddplugins) 
    961310148            { 
    9614                 if(!(ddpi.flags & DDPI.NOTLOADING) 
    9615                     && (ddpi.fullpath.length < 5 || std.string.icmp(".dapi", ddpi.fullpath[$ - 5 .. $])) ) 
     10149                if(ddpi.flags & DDPI.NOTLOADING) 
     10150                { 
     10151                    continue; 
     10152                } 
     10153                //msgBox("loading plugin: " ~ ddpi.fullpath); 
     10154                if(ddpi.flags & DDPI.BUILTIN) 
     10155                { 
     10156                    Plugin plug = getBuiltinPlugin(ddpi.fullpath); 
     10157                    ddpi.flags |= DDPI.LOADED; 
     10158                    registerPlugin(plug); 
     10159                    continue; 
     10160                } 
     10161                if(ddpi.fullpath.length < 5 
     10162                    || !(!std.string.icmp(".dapi", ddpi.fullpath[$ - 5 .. $]) 
     10163                        || !std.string.icmp(".json", ddpi.fullpath[$ - 5 .. $])) 
     10164                    ) 
    961610165                { 
    961710166                    int errnum; 
     10167                     // Doesn't call plugin's "loaded" yet. 
    961810168                    emsg = loadDllPlugin(ddpi.fullpath, plug, true, errnum); 
    961910169                    if(emsg.length) 
     
    963910189                        ddpi.flags |= DDPI.LOADED; 
    964010190                         
     10191                        // Doesn't call plugin's "loaded" yet. 
     10192                        // Only registers with Entice internals (e.g. w/ plugin ID) 
    964110193                        registerPlugin(plug); 
    964210194                    } 
     
    967810230     
    967910231    // Can't use DflCompat.FORM_DIALOGRESULT_096 (zorderform and perhaps others depend on the new impl) 
     10232     
     10233    debug(Entice_fakeMultipleScreens) 
     10234    { 
     10235        Screen.fakeMultipleScreens = true; 
     10236    } 
    968010237     
    968110238    try 
     
    985510412        } 
    985610413        config_found: ; 
     10414        //compile.compileConfigDir = localdir; 
    985710415         
    985810416        if(_install) 
     
    990010458         
    990110459        // Want the plugins to be there for the file loading. 
    9902         loadPlugins(); 
     10460        setupPlugins(); 
    990310461        pluginsloaded = true; 
    990410462         
     
    990810466        Application.doEvents(); 
    990910467         
    9910         mainForm.tellPluginsLoaded(); 
     10468        // Calls the plugins' "loaded"! 
     10469        // This handles 'default' plugins, etc. 
     10470        mainForm.finishPluginsLoaded(); 
    991110471         
    991210472        Application.doEvents(); // In case the plugins post messages. 
     
    992510485            Application.onThreadException(e); 
    992610486        } 
     10487         
     10488        /+ 
     10489        { 
     10490            struct fff { import promptbox; } 
     10491            scope pf = (new fff.PromptForm("Plugins Loaded")) 
     10492                .enableButtons(false); 
     10493            foreach(Plugin plug; plugins.plugins) 
     10494            { 
     10495                pf.addLabel("Plugin: " ~ plug.fname); 
     10496            } 
     10497            pf.showDialog(); 
     10498            pf.dispose(); 
     10499        } 
     10500        +/ 
    992710501         
    992810502        apprun = true; 
  • trunk/win32/entice/dfldesigner.rc

    r101 r102  
    7979            VALUE "FileVersion", "0.8.6\0" 
    8080            VALUE "InternalName", "entice" 
    81             VALUE "LegalCopyright", "Copyright (C) 2004-2008 Christopher E. Miller" 
     81            VALUE "LegalCopyright", "Copyright (C) 2004-2009 Christopher E. Miller" 
    8282            VALUE "OriginalFilename", "entice.exe" 
    8383            VALUE "ProductName", "Entice Designer\0" 
  • trunk/win32/entice/dirchanges.d

    r101 r102  
    154154    } 
    155155     
    156     HANDLE hwait = dfl.utf.findFirstChangeNotification(dir, FALSE, 
     156    HANDLE hwait = dfl.internal.utf.findFirstChangeNotification(dir, FALSE, 
    157157        FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE 
    158158        | FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME); 
  • trunk/win32/entice/drawing.d

    r101 r102  
    33 
    44 
    5 private import dfl.all, dfl.winapi; 
     5private import dfl.all, dfl.internal.winapi; 
    66 
    77 
  • trunk/win32/entice/dscale.d

    r101 r102  
    33 
    44 
    5 private import dfl.all, dfl.winapi; 
     5private import dfl.all, dfl.internal.winapi; 
    66 
    77 
  • trunk/win32/entice/editorexprops.d

    r101 r102  
    9898        picBox.name = "picBox"; 
    9999        picBox.sizeMode = dfl.picturebox.PictureBoxSizeMode.CENTER_IMAGE; 
    100         picBox.bounds = dfl.base.Rect(8, 8, 23, 23); 
     100        picBox.bounds = dfl.all.Rect(8, 8, 23, 23); 
    101101        picBox.parent = this; 
    102102        //~DFL dfl.groupbox.GroupBox=groupBox1 
     
    104104        groupBox1.name = "groupBox1"; 
    105105        groupBox1.text = "Encoding"; 
    106         groupBox1.bounds = dfl.base.Rect(8, 40, 296, 92); 
     106        groupBox1.bounds = dfl.all.Rect(8, 40, 296, 92); 
    107107        groupBox1.parent = this; 
    108108        //~DFL dfl.button.RadioButton=utf8radio 
     
    110110        utf8radio.name = "utf8radio"; 
    111111        utf8radio.text = "UTF-8 (Recommended)"; 
    112         utf8radio.bounds = dfl.base.Rect(12, 17, 171, 23); 
     112        utf8radio.bounds = dfl.all.Rect(12, 17, 171, 23); 
    113113        utf8radio.parent = groupBox1; 
    114114        //~DFL dfl.button.RadioButton=utf16leRadio 
     
    116116        utf16leRadio.name = "utf16leRadio"; 
    117117        utf16leRadio.text = "UTF-16 LE (Windows Unicode)"; 
    118         utf16leRadio.bounds = dfl.base.Rect(12, 41, 171, 23); 
     118        utf16leRadio.bounds = dfl.all.Rect(12, 41, 171, 23); 
    119119        utf16leRadio.parent = groupBox1; 
    120120        //~DFL dfl.button.RadioButton=utf32leRadio 
     
    122122        utf32leRadio.name = "utf32leRadio"; 
    123123        utf32leRadio.text = "UTF-32 LE"; 
    124         utf32leRadio.bounds = dfl.base.Rect(12, 65, 171, 23); 
     124        utf32leRadio.bounds = dfl.all.Rect(12, 65, 171, 23); 
    125125        utf32leRadio.parent = groupBox1; 
    126126        //~DFL dfl.button.RadioButton=utf16beRadio 
     
    128128        utf16beRadio.name = "utf16beRadio"; 
    129129        utf16beRadio.text = "UTF-16 BE"; 
    130         utf16beRadio.bounds = dfl.base.Rect(196, 41, 83, 23); 
     130        utf16beRadio.bounds = dfl.all.Rect(196, 41, 83, 23); 
    131131        utf16beRadio.parent = groupBox1; 
    132132        //~DFL dfl.button.RadioButton=utf32beRadio 
     
    134134        utf32beRadio.name = "utf32beRadio"; 
    135135        utf32beRadio.text = "UTF-32 BE"; 
    136         utf32beRadio.bounds = dfl.base.Rect(196, 65, 83, 23); 
     136        utf32beRadio.bounds = dfl.all.Rect(196, 65, 83, 23); 
    137137        utf32beRadio.parent = groupBox1; 
    138138        //~DFL dfl.button.Button=okBtn 
     
    140140        okBtn.name = "okBtn"; 
    141141        okBtn.text = "OK"; 
    142         okBtn.bounds = dfl.base.Rect(152, 144, 75, 23); 
     142        okBtn.bounds = dfl.all.Rect(152, 144, 75, 23); 
    143143        okBtn.parent = this; 
    144144        //~DFL dfl.button.Button=cancelBtn 
     
    146146        cancelBtn.name = "cancelBtn"; 
    147147        cancelBtn.text = "Cancel"; 
    148         cancelBtn.bounds = dfl.base.Rect(232, 144, 75, 23); 
     148        cancelBtn.bounds = dfl.all.Rect(232, 144, 75, 23); 
    149149        cancelBtn.parent = this; 
    150150        //~DFL EEXP_PathLabel:dfl.textbox.TextBox=itemNameDisp 
     
    154154        itemNameDisp.text = "Foo"; 
    155155        itemNameDisp.borderStyle = dfl.base.BorderStyle.NONE; 
    156         itemNameDisp.bounds = dfl.base.Rect(34, 12, 268, 23); 
     156        itemNameDisp.bounds = dfl.all.Rect(34, 12, 268, 23); 
    157157        itemNameDisp.parent = this; 
    158158        //~Entice Designer 0.8.2pre6 code ends here. 
  • trunk/win32/entice/editorstyler.d

    r101 r102  
    33 
    44 
    5 private import dfl.all, dfl.winapi; 
     5private import dfl.all, dfl.internal.winapi; 
    66 
    77 
  • trunk/win32/entice/etabber.d

    r101 r102  
    2424     
    2525     
     26    bool allowDetach = false; 
     27     
     28     
    2629    /// 
    2730    final bool showSplit() // getter 
  • trunk/win32/entice/findreplace.d

    r101 r102  
    44 
    55private import std.string, std.path; 
    6 private import dfl.all, dfl.winapi; 
     6private import dfl.all, dfl.internal.winapi; 
    77 
    88 
     
    453453        label1.text = "Fi&nd what:"; 
    454454        label1.textAlign = dfl.base.ContentAlignment.MIDDLE_LEFT; 
    455         label1.bounds = dfl.base.Rect(8, 8, 76, 23); 
     455        label1.bounds = dfl.all.Rect(8, 8, 76, 23); 
    456456        label1.parent = this; 
    457457        //~DFL dfl.combobox.ComboBox=findBox 
    458458        findBox = new dfl.combobox.ComboBox(); 
    459459        findBox.name = "findBox"; 
    460         findBox.bounds = dfl.base.Rect(88, 8, 200, 21); 
     460        findBox.bounds = dfl.all.Rect(88, 8, 200, 21); 
    461461        findBox.parent = this; 
    462462        //~DFL dfl.label.Label=replaceLabel 
     
    465465        replaceLabel.text = "Re&place with:"; 
    466466        replaceLabel.textAlign = dfl.base.ContentAlignment.MIDDLE_LEFT; 
    467         replaceLabel.bounds = dfl.base.Rect(8, 40, 76, 23); 
     467        replaceLabel.bounds = dfl.all.Rect(8, 40, 76, 23); 
    468468        replaceLabel.parent = this; 
    469469        //~DFL dfl.combobox.ComboBox=replaceBox 
    470470        replaceBox = new dfl.combobox.ComboBox(); 
    471471        replaceBox.name = "replaceBox"; 
    472         replaceBox.bounds = dfl.base.Rect(88, 40, 200, 21); 
     472        replaceBox.bounds = dfl.all.Rect(88, 40, 200, 21); 
    473473        replaceBox.parent = this; 
    474474        //~DFL dfl.button.CheckBox=wholeWordCheck 
     
    476476        wholeWordCheck.name = "wholeWordCheck"; 
    477477        wholeWordCheck.text = "Match &whole word only"; 
    478         wholeWordCheck.bounds = dfl.base.Rect(8, 72, 243, 23); 
     478        wholeWordCheck.bounds = dfl.all.Rect(8, 72, 243, 23); 
    479479        wholeWordCheck.parent = this; 
    480480        //~DFL dfl.button.CheckBox=caseCheck 
     
    482482        caseCheck.name = "caseCheck"; 
    483483        caseCheck.text = "Match &case"; 
    484         caseCheck.bounds = dfl.base.Rect(8, 92, 243, 23); 
     484        caseCheck.bounds = dfl.all.Rect(8, 92, 243, 23); 
    485485        caseCheck.parent = this; 
    486486        //~DFL dfl.button.CheckBox=regexCheck 
     
    488488        regexCheck.name = "regexCheck"; 
    489489        regexCheck.text = "Regular &expression"; 
    490         regexCheck.bounds = dfl.base.Rect(8, 112, 243, 23); 
     490        regexCheck.bounds = dfl.all.Rect(8, 112, 243, 23); 
    491491        regexCheck.parent = this; 
    492492        //~DFL dfl.button.CheckBox=wrapCheck 
     
    494494        wrapCheck.name = "wrapCheck"; 
    495495        wrapCheck.text = "Wrap aroun&d"; 
    496         wrapCheck.bounds = dfl.base.Rect(8, 132, 243, 23); 
     496        wrapCheck.bounds = dfl.all.Rect(8, 132, 243, 23); 
    497497        wrapCheck.parent = this; 
    498498        //~DFL dfl.button.CheckBox=escapeCharCheck 
     
    500500        escapeCharCheck.name = "escapeCharCheck"; 
    501501        escapeCharCheck.text = "Transform &backslash expressions"; 
    502         escapeCharCheck.bounds = dfl.base.Rect(8, 152, 243, 23); 
     502        escapeCharCheck.bounds = dfl.all.Rect(8, 152, 243, 23); 
    503503        escapeCharCheck.parent = this; 
    504504        //~DFL dfl.button.CheckBox=transCheck 
     
    506506        transCheck.name = "transCheck"; 
    507507        transCheck.text = "Dialog &Transparency"; 
    508         transCheck.bounds = dfl.base.Rect(8, 172, 211, 23); 
     508        transCheck.bounds = dfl.all.Rect(8, 172, 211, 23); 
    509509        transCheck.parent = this; 
    510510        //~DFL dfl.button.Button=findNextBtn 
     
    512512        findNextBtn.name = "findNextBtn"; 
    513513        findNextBtn.text = "&Find Next"; 
    514         findNextBtn.bounds = dfl.base.Rect(296, 8, 123, 23); 
     514        findNextBtn.bounds = dfl.all.Rect(296, 8, 123, 23); 
    515515        findNextBtn.parent = this; 
    516516        //~DFL dfl.button.Button=replaceBtn 
     
    518518        replaceBtn.name = "replaceBtn"; 
    519519        replaceBtn.text = "&Replace"; 
    520         replaceBtn.bounds = dfl.base.Rect(296, 40, 123, 23); 
     520        replaceBtn.bounds = dfl.all.Rect(296, 40, 123, 23); 
    521521        replaceBtn.parent = this; 
    522522        //~DFL dfl.button.Button=replaceAllBtn 
     
    524524        replaceAllBtn.name = "replaceAllBtn"; 
    525525        replaceAllBtn.text = "Replace &All"; 
    526         replaceAllBtn.bounds = dfl.base.Rect(296, 72, 123, 23); 
     526        replaceAllBtn.bounds = dfl.all.Rect(296, 72, 123, 23); 
    527527        replaceAllBtn.parent = this; 
    528528        //~DFL dfl.button.Button=replaceInSelectionBtn 
     
    530530        replaceInSelectionBtn.name = "replaceInSelectionBtn"; 
    531531        replaceInSelectionBtn.text = "Replace in &Selection"; 
    532         replaceInSelectionBtn.bounds = dfl.base.Rect(296, 104, 123, 23); 
     532        replaceInSelectionBtn.bounds = dfl.all.Rect(296, 104, 123, 23); 
    533533        replaceInSelectionBtn.parent = this; 
    534534        //~DFL dfl.button.Button=closeBtn 
     
    536536        closeBtn.name = "closeBtn"; 
    537537        closeBtn.text = "Close"; 
    538         closeBtn.bounds = dfl.base.Rect(296, 136, 123, 23); 
     538        closeBtn.bounds = dfl.all.Rect(296, 136, 123, 23); 
    539539        closeBtn.parent = this; 
    540540        //~DFL dfl.label.Label=tempText 
     
    542542        tempText.name = "tempText"; 
    543543        tempText.textAlign = dfl.base.ContentAlignment.BOTTOM_RIGHT; 
    544         tempText.bounds = dfl.base.Rect(224, 168, 192, 23); 
     544        tempText.bounds = dfl.all.Rect(224, 168, 192, 23); 
    545545        tempText.parent = this; 
    546546        //~Entice Designer 0.8.2.1 code ends here. 
  • trunk/win32/entice/inputform.d

    r101 r102  
    6969        inputBox = new dfl.textbox.TextBox(); 
    7070        inputBox.name = "inputBox"; 
    71         inputBox.bounds = dfl.base.Rect(8, 64, 280, 23); 
     71        inputBox.bounds = dfl.all.Rect(8, 64, 280, 23); 
    7272        inputBox.parent = this; 
    7373        //~DFL dfl.label.Label=inputLabel 
    7474        inputLabel = new dfl.label.Label(); 
    7575        inputLabel.name = "inputLabel"; 
    76         inputLabel.bounds = dfl.base.Rect(8, 8, 276, 47); 
     76        inputLabel.bounds = dfl.all.Rect(8, 8, 276, 47); 
    7777        inputLabel.parent = this; 
    7878        //~DFL dfl.button.Button=okBtn 
     
    8080        okBtn.name = "okBtn"; 
    8181        okBtn.text = "OK"; 
    82         okBtn.bounds = dfl.base.Rect(128, 96, 75, 23); 
     82        okBtn.bounds = dfl.all.Rect(128, 96, 75, 23); 
    8383        okBtn.parent = this; 
    8484        //~DFL dfl.button.Button=cancelBtn 
     
    8686        cancelBtn.name = "cancelBtn"; 
    8787        cancelBtn.text = "Cancel"; 
    88         cancelBtn.bounds = dfl.base.Rect(208, 96, 75, 23); 
     88        cancelBtn.bounds = dfl.all.Rect(208, 96, 75, 23); 
    8989        cancelBtn.parent = this; 
    9090        //~Entice Designer 0.8.1 code ends here. 
  • trunk/win32/entice/mak.bat

    r101 r102  
    11@cls 
     2 
     3set dmdpath=c:\dmd 
     4set dimports=f:\christop\d\import 
     5 
     6set dfl_options=-version=DFL_MULTIPLE_SCREENS 
    27 
    38 
    49rcc -32 dfldesigner.rc 
    5 dfl -d -gui -version=START_PAGE -version=DESIGN_PROP_INFO %dfl_flags% -Jimages -ofentice.exe dfldesigner %1 %2 %3 %4 %5 -version=ETABSCROLL -version=ONLYFOCUSDESIGNITEMPARENT -version=ADVANCED_FIND advfindpanel ddfiletypes projectmanager ddprojectmanager aboutform apiviewer apiinfo waitmanager dirchanges startpage ddopenparser inputform inputnumber scistyles options dscale editorstyler ddeditorstyler ddoptions ddoptsfiletypespanel ddoptsdesignpanel ddoptsgeneralpanel ddoptspluginspanel ddoptseditorpanel ddoptsnetworkpanel findreplace ddfindreplace util drawing sourcegen parse dflparse tabber proppanel etabber toolbox dddesignform dddesigncontrol ddcontrolchildren newform design designform designcontrol dockstyleform ddcontrolspace scintilladlex checkup ddexprops editorexprops ddwininet zorderform plugins filterfindbox resource shell32.lib c:\dmd\import\dfl\scintilla.d dfldesigner.res dfldesigner.def -Id:\d\import d:\d\import\rgroup.d d:\d\import\rdflregistry.d d:\d\import\rini.d d:\d\import\ini.d 
     10 
     11@set entice_mode=-debug -gui 
     12@rem @set entice_mode=-O -inline -gui 
     13@rem @set entice_mode=-debug=Entice_fakeMultipleScreens -debug -unittest -gui 
     14 
     15dfl %entice_mode% -d -version=START_PAGE -version=TABBER_NO_DETACH -version=ENTICE_MULTISEL -version=DESIGN_PROP_INFO %dfl_flags% -Jimages -ofentice.exe dfldesigner -version=ETABSCROLL -version=ONLYFOCUSDESIGNITEMPARENT -version=ADVANCED_FIND advfindpanel ddfiletypes usereditlistbox promptbox downloaderpanel projectmanager ddprojectmanager aboutform apiviewer apiinfo waitmanager dirchanges startpage ddopenparser inputform inputnumber scistyles options dscale editorstyler ddeditorstyler ddoptions ddoptsfiletypespanel ddoptsdesignpanel ddoptsgeneralpanel ddoptspluginspanel ddoptseditorpanel ddoptsnetworkpanel ddoptscompilerpanel findreplace ddfindreplace util drawing sourcegen parse dflparse tabber proppanel etabber toolbox dddesignform dddesigncontrol ddcontrolchildren newform design designform designcontrol dockstyleform ddcontrolspace scintilladlex checkup ddexprops editorexprops ddwininet zorderform plugins filterfindbox compile firstsetupstartpagepanel dlangselectorpanel dinstallform dmdversionselectorpanel savetodirpanel resource winapi shell32.lib %dmdpath%\import\dfl\scintilla.d %dmdpath%\import\dfl\cpp\scintilla.d dfldesigner.res process -I%dimports% %dimports%\rgroup.d %dimports%\rdflregistry.d %dimports%\rini.d %dimports%\ini.d 
     16 
    617 
    718 
  • trunk/win32/entice/newform.d

    r101 r102  
    44 
    55private import std.path, std.file, std.string; 
    6 private import dfl.all, dfl.winapi; 
     6private import dfl.all, dfl.internal.winapi; 
    77 
    88private import dfldesigner, design, util; 
     
    736736        nameLabel.text = "&Name:"; 
    737737        nameLabel.textAlign = dfl.base.ContentAlignment.MIDDLE_LEFT; 
    738         nameLabel.bounds = dfl.base.Rect(144, 8, 92, 23); 
     738        nameLabel.bounds = dfl.all.Rect(144, 8, 92, 23); 
    739739        nameLabel.parent = this; 
    740740        //~DFL dfl.textbox.TextBox=myFormBox 
    741741        myFormBox = new dfl.textbox.TextBox(); 
    742742        myFormBox.name = "myFormBox"; 
    743         myFormBox.bounds = dfl.base.Rect(240, 8, 184, 23); 
     743        myFormBox.bounds = dfl.all.Rect(240, 8, 184, 23); 
    744744        myFormBox.parent = this; 
    745745        //~DFL dfl.label.Label=fileNameLabel 
     
    748748        fileNameLabel.text = "&File name:"; 
    749749        fileNameLabel.textAlign = dfl.base.ContentAlignment.MIDDLE_LEFT; 
    750         fileNameLabel.bounds = dfl.base.Rect(144, 40, 92, 23); 
     750        fileNameLabel.bounds = dfl.all.Rect(144, 40, 92, 23); 
    751751        fileNameLabel.parent = this; 
    752752        //~DFL dfl.textbox.TextBox=fileBox 
    753753        fileBox = new dfl.textbox.TextBox(); 
    754754        fileBox.name = "fileBox"; 
    755         fileBox.bounds = dfl.base.Rect(240, 40, 184, 23); 
     755        fileBox.bounds = dfl.all.Rect(240, 40, 184, 23); 
    756756        fileBox.parent = this; 
    757757        //~DFL dfl.label.Label=label6 
     
    760760        label6.text = "Save &in:"; 
    761761        label6.textAlign = dfl.base.ContentAlignment.MIDDLE_LEFT; 
    762         label6.bounds = dfl.base.Rect(144, 72, 92, 23); 
     762        label6.bounds = dfl.all.Rect(144, 72, 92, 23); 
    763763        label6.parent = this; 
    764764        //~DFL dfl.textbox.TextBox=dirBox 
    765765        dirBox = new dfl.textbox.TextBox(); 
    766766        dirBox.name = "dirBox"; 
    767         dirBox.bounds = dfl.base.Rect(240, 72, 184, 23); 
     767        dirBox.bounds = dfl.all.Rect(240, 72, 184, 23); 
    768768        dirBox.parent = this; 
    769769        //~DFL dfl.button.Button=dirBrowseBtn 
     
    771771        dirBrowseBtn.name = "dirBrowseBtn"; 
    772772        dirBrowseBtn.text = "&Browse..."; 
    773         dirBrowseBtn.bounds = dfl.base.Rect(352, 104, 75, 23); 
     773        dirBrowseBtn.bounds = dfl.all.Rect(352, 104, 75, 23); 
    774774        dirBrowseBtn.parent = this; 
    775775        //~DFL dfl.label.Label=label7 
     
    778778        label7.text = "Save as:"; 
    779779        label7.autoSize = true; 
    780         label7.bounds = dfl.base.Rect(144, 112, 42, 13); 
     780        label7.bounds = dfl.all.Rect(144, 112, 42, 13); 
    781781        label7.parent = this; 
    782782        //~DFL dfl.button.Button=createBtn 
     
    784784        createBtn.name = "createBtn"; 
    785785        createBtn.text = "&Create"; 
    786         createBtn.bounds = dfl.base.Rect(272, 168, 75, 23); 
     786        createBtn.bounds = dfl.all.Rect(272, 168, 75, 23); 
    787787        createBtn.parent = this; 
    788788        //~DFL dfl.button.Button=cancelBtn 
     
    790790        cancelBtn.name = "cancelBtn"; 
    791791        cancelBtn.text = "Cancel"; 
    792         cancelBtn.bounds = dfl.base.Rect(352, 168, 75, 23); 
     792        cancelBtn.bounds = dfl.all.Rect(352, 168, 75, 23); 
    793793        cancelBtn.parent = this; 
    794794        //~DFL dfl.listbox.ListBox=itemList 
     
    797797        itemList.drawMode = dfl.base.DrawMode.OWNER_DRAW_FIXED; 
    798798        itemList.integralHeight = false; 
    799         itemList.bounds = dfl.base.Rect(8, 8, 120, 184); 
     799        itemList.bounds = dfl.all.Rect(8, 8, 120, 184); 
    800800        itemList.parent = this; 
    801801        //~DFL FileDispLabel:dfl.label.Label=saveDisp 
     
    804804        saveDisp.borderStyle = dfl.base.BorderStyle.FIXED_3D; 
    805805        saveDisp.textAlign = dfl.base.ContentAlignment.MIDDLE_LEFT; 
    806         saveDisp.bounds = dfl.base.Rect(136, 136, 292, 23); 
     806        saveDisp.bounds = dfl.all.Rect(136, 136, 292, 23); 
    807807        saveDisp.parent = this; 
    808808        //~Entice Designer 0.8pre8 code ends here. 
  • trunk/win32/entice/options.d

    r101 r102  
    66private import dfl.all; 
    77private import tabber, winapi; 
     8 
     9import usereditlistbox; 
    810 
    911import dscale; 
     
    714716 
    715717 
     718class OptListBox: ListBox, IOpt 
     719{ 
     720    mixin ApplyOpt; 
     721     
     722     
     723    this(char[] optName, uint32_t optId) 
     724    { 
     725        optname = optName; 
     726        optid = optId; 
     727    } 
     728     
     729     
     730    bit isOptDirty() // getter 
     731    { 
     732        return isdirty; 
     733    } 
     734     
     735     
     736    char[] optName() // getter 
     737    { 
     738        return optname; 
     739    } 
     740     
     741     
     742    uint32_t gid() // getter 
     743    { 
     744        return optid; 
     745    } 
     746     
     747     
     748    RegistryValue getOptValue() 
     749    { 
     750        char[][] x = new char[][this.items.length]; 
     751        for(int i = 0; i < x.length; i++) 
     752        { 
     753            x[i] = this.items[i].toString(); 
     754        } 
     755        RegistryValueMultiSz rval = new RegistryValueMultiSz(); 
     756        rval.value = x; 
     757        return rval; 
     758    } 
     759     
     760     
     761    // Sets the value and makes it not dirty. 
     762    bit setOptValue(RegistryValue regval) 
     763    { 
     764        RegistryValueMultiSz rval; 
     765        rval = cast(RegistryValueMultiSz)regval; 
     766        if(rval) 
     767        { 
     768            this.items.clear(); 
     769            for(int i = 0; i < rval.value.length; i++) 
     770            { 
     771                this.items.add(rval.value[i]); 
     772            } 
     773            isdirty = false; 
     774            return true; 
     775        } 
     776        return false; 
     777    } 
     778     
     779     
     780    // This is here because this list can't get dirty by itself. 
     781    // Need user handling code to dirty it (e.g. OptUserEditListBox). 
     782    void setDirty() 
     783    { 
     784        isdirty = true; 
     785    } 
     786     
     787     
     788    char[] optname; 
     789    uint32_t optid; 
     790    bit isdirty = false; 
     791} 
     792 
     793 
     794class OptUserEditListBox: UserEditListBox, IOpt 
     795{ 
     796    mixin ApplyOpt; 
     797     
     798    OptListBox optlist; 
     799     
     800     
     801    this(char[] optName, uint32_t optId) 
     802    { 
     803        optlist = new OptListBox(optName, optId); 
     804        super(); 
     805    } 
     806     
     807     
     808    bit isOptDirty() // getter 
     809    { 
     810        return optlist.isOptDirty; 
     811    } 
     812     
     813     
     814    char[] optName() // getter 
     815    { 
     816        return optlist.optName; 
     817    } 
     818     
     819     
     820    uint32_t gid() // getter 
     821    { 
     822        return optlist.gid; 
     823    } 
     824     
     825     
     826    RegistryValue getOptValue() 
     827    { 
     828        return optlist.getOptValue(); 
     829    } 
     830     
     831     
     832    // Sets the value and makes it not dirty. 
     833    bit setOptValue(RegistryValue regval) 
     834    { 
     835        return optlist.setOptValue(regval); 
     836    } 
     837     
     838     
     839    protected override ListBox createListBox() 
     840    { 
     841        return optlist; 
     842    } 
     843     
     844     
     845    protected override void onUserEdited(EventArgs ea) 
     846    { 
     847        super.onUserEdited(ea); 
     848         
     849        optlist.setDirty(); 
     850    } 
     851     
     852} 
     853 
     854 
    716855class OptTab: Tab, IId 
    717856{ 
     
    820959        maximizeBox = false; 
    821960        sizingGrip = true; 
    822         //size = Size(400 + 30, 320 + 30); // Tad bigger than least. 
    823         size = Size(500, 400); // Tad bigger than least. 
     961        size = Size(480, 420); // Tad bigger than least. 
    824962        startPosition = FormStartPosition.CENTER_PARENT; 
    825963        showInTaskbar = false; 
     
    853991        addShortcut(Keys.CONTROL | Keys.TAB, &shortcut_ctrlTab); 
    854992         
     993        //closing ~= &form_closing; 
     994         
    855995        resumeLayout(false); 
    856996    } 
     997     
     998     
     999    /* 
     1000    void form_closing(Object sender, CancelEventArgs ea) 
     1001    { 
     1002        tabs.removeAllTabs(); 
     1003    } 
     1004    */ 
    8571005     
    8581006     
  • trunk/win32/entice/parse.d

    r101 r102  
    877877                                                         
    878878                                                        default: 
    879                                                             if(!std.string.isspace(ch)) 
     879                                                            if(!std.ctype.isspace(ch)) 
    880880                                                            { 
    881881                                                                warnOrErr("Expected end of line."); 
     
    947947    // Returns null dchar at end instead of throwing exception. 
    948948    final dchar getc() 
    949     in 
    950949    { 
    951950        assert(ungettok.type == TokenType.NONE); 
    952     } 
    953     body 
    954     { 
     951         
    955952        dchar result; 
    956953         
     
    1002999    // Single unget only. 
    10031000    final void ungetc(dchar ch) 
    1004     in 
    10051001    { 
    10061002        assert(!unget); 
    1007     } 
    1008     body 
    1009     { 
     1003         
    10101004        unget = ch; 
    10111005    } 
     
    13441338     
    13451339    final void ungetToken(Token tok) 
    1346     in 
    13471340    { 
    13481341        assert(ungettok.type == TokenType.NONE); 
    13491342        assert(!ungettok.str.length); 
    13501343        assert(tok.type != TokenType.NONE); 
    1351     } 
    1352     body 
    1353     { 
     1344         
    13541345        ungettok = tok; 
    13551346         
     
    13701361    //protected Token getNewToken() 
    13711362    protected void getNewToken(out Token result) 
    1372     in 
    1373     { 
    1374         assert(ungettok.type == TokenType.NONE); 
    1375     } 
    1376     body 
    1377     { 
     1363    { 
     1364        assert(ungettok.type == TokenType.NONE, 
     1365            "getNewToken: (ungettok.type == TokenType.NONE)"); 
     1366         
    13781367        //Token result; 
    13791368        dchar ch; 
  • trunk/win32/entice/plugins.d

    r101 r102  
    33 
    44 
    5 import winapi, dfl.all, dfl.utf; 
     5import winapi, dfl.all, dfl.internal.utf; 
    66 
    77import std.gc, std.path, std.string, std.c.stdlib, 
     
    645645                                if(ent.filePath.length) 
    646646                                { 
    647                                     auto dcmd= new DoCmd(plug.name, (cast(char*)getinfo)[0 .. getinfosize], getDirName(ent.filePath), true); 
     647                                    DoCmd dcmd = new DoCmd(plug.name, (cast(char*)getinfo)[0 .. getinfosize], getDirName(ent.filePath), true); 
    648648                                    dcmd.start(); 
    649649                                    // Note: don't stop, delete (or auto) dcmd because it's still running! 
     
    666666                                if(ent.filePath.length) 
    667667                                { 
    668                                     auto dcmd= new DoCmd(plug.name, (cast(char*)getinfo)[0 .. getinfosize], getDirName(ent.filePath), true); 
     668                                    DoCmd dcmd = new DoCmd(plug.name, (cast(char*)getinfo)[0 .. getinfosize], getDirName(ent.filePath), true); 
    669669                                    dcmd.cmdpause = false; 
    670670                                    dcmd.start(); 
     
    15331533extern(Windows) 
    15341534{ 
    1535     alias int function(EnticePluginInfo*) EnticePluginLoadProc; 
     1535    alias int function(EnticePluginInfo*) EnticePluginInfoProc; 
    15361536    alias void function(EnticeFunctions*) EnticePluginLoadedProc; 
    15371537    alias void function(EnticeFunctions* efuncs, int n) EnticePluginUnloadedProc; 
     
    19561956     
    19571957    HMODULE hmod; 
     1958    bool hasPluginLoaded = false; // Plugin loaded signaled. 
    19581959     
    19591960    PluginMenuItem[] menus; 
     
    20262027    protected void registered() 
    20272028    { 
    2028          
    2029     } 
    2030      
    2031      
    2032     void dispose(bool unloadDLL = true) 
    2033     { 
    2034         if(hmod.init != hmod) 
    2035         { 
    2036             auto unloadedproc = cast(EnticePluginUnloadedProc)getPluginProcAddr(hmod, "enticePluginUnloaded", 2); 
    2037             if(unloadedproc) 
     2029    } 
     2030     
     2031     
     2032    // Called by pluginLoad(). 
     2033    protected void loaded() 
     2034    { 
     2035    } 
     2036     
     2037     
     2038    // Called by dispose(). 
     2039    protected void unloading() 
     2040    { 
     2041    } 
     2042     
     2043     
     2044    // Called by signalOnePluginLoaded(). 
     2045    protected final void pluginLoad() 
     2046    { 
     2047        hasPluginLoaded = true; 
     2048         
     2049        // Using "new" to get completely new address. 
     2050        efuncs = new EnticeFunctions; 
     2051        efuncs.pluginid = pluginid; 
     2052     
     2053        if(hmod) 
     2054        { 
     2055            EnticePluginLoadedProc loadedproc; 
     2056            loadedproc = cast(EnticePluginLoadedProc)getPluginProcAddr(hmod, "enticePluginLoaded", 1); 
     2057            // OK if not there, they just don't care about the loaded event. 
     2058            if(loadedproc) 
    20382059            { 
    20392060                try 
    20402061                { 
    2041                     unloadedproc(efuncs, unloadDLL ? 1 : 2); 
    2042                      
    2043                     if(unloadDLL) 
    2044                         FreeLibrary(hmod); // Only if successfully returned from unload proc. 
     2062                    loadedproc(efuncs); 
    20452063                } 
    20462064                catch 
    20472065                { 
    2048                     // If unloadedproc threw, leak the DLL, otherwise bad things could happen. 
     2066                } 
     2067            } 
     2068        } 
     2069         
     2070        loaded(); 
     2071         
     2072    } 
     2073     
     2074     
     2075    void dispose(bool unloadDLL = true) 
     2076    { 
     2077        unloading(); 
     2078         
     2079        bool prev_hasPluginLoaded = hasPluginLoaded; 
     2080        hasPluginLoaded = false; 
     2081        if(hmod.init != hmod) 
     2082        { 
     2083            if(prev_hasPluginLoaded) 
     2084            { 
     2085                auto unloadedproc = cast(EnticePluginUnloadedProc)getPluginProcAddr(hmod, "enticePluginUnloaded", 2); 
     2086                if(unloadedproc) 
     2087                { 
     2088                    try 
     2089                    { 
     2090                        unloadedproc(efuncs, unloadDLL ? 1 : 2); 
     2091                         
     2092                        if(unloadDLL) 
     2093                            FreeLibrary(hmod); // Only if successfully returned from unload proc. 
     2094                    } 
     2095                    catch 
     2096                    { 
     2097                        // If unloadedproc threw, leak the DLL, otherwise bad things could happen. 
     2098                    } 
     2099                } 
     2100                else 
     2101                { 
     2102                    if(unloadDLL) 
     2103                        FreeLibrary(hmod); 
    20492104                } 
    20502105            } 
     
    21322187        } 
    21332188         
    2134         pluginid = rand() & 0xFFFFFFF; 
     2189        pluginid = rand() & 0x0FFFFFFF; 
    21352190        if(!(pluginid in plugins)) 
    21362191            break; 
     
    21442199 
    21452200 
     2201/+ 
     2202void signalPluginsLoaded() 
     2203{ 
     2204    foreach(Plugin plug in plugins) 
     2205    { 
     2206        signalOnePluginLoaded(plug); 
     2207    } 
     2208} 
     2209+/ 
     2210 
     2211 
    21462212void signalOnePluginLoaded(Plugin plug) 
    21472213{ 
    2148     EnticePluginLoadedProc loadedproc; 
    2149     loadedproc = cast(EnticePluginLoadedProc)getPluginProcAddr(plug.hmod, "enticePluginLoaded", 1); 
    2150     if(!loadedproc) // OK, they just don't care about the loaded event. 
    2151         return; 
    2152      
    2153     try 
    2154     { 
    2155         // Using "new" to get completely new address. 
    2156         plug.efuncs = new EnticeFunctions; 
    2157         plug.efuncs.pluginid = plug.pluginid; 
    2158         loadedproc(plug.efuncs); 
    2159     } 
    2160     catch 
    2161     { 
    2162     } 
    2163 
    2164  
    2165  
    2166 void signalPluginsLoaded() 
    2167 
    2168     foreach(Plugin plug; plugins) 
    2169     { 
    2170         signalOnePluginLoaded(plug); 
    2171     } 
     2214    plug.pluginLoad(); 
    21722215} 
    21732216 
     
    22292272    PLUGIN_CODECOMPLETION = 0x00040000, /// EnticePluginInfo flag: A plugin sets this if it provides code autocompletion. 
    22302273    PLUGIN_CODELAYOUTTAB = 0x00080000, /// EnticePluginInfo flag: A plugin sets this if it provides code layout for open files. 
     2274     
     2275    PLUGIN_DEFAULT2 = 0x00100000, /// EnticePluginInfo flag: A plugin sets this to be between a PLUGIN_DEFAULT plugin and a normal one. Built-in plugins set this. 
     2276     
     2277    PLUGIN_SAFEUNLOAD = 0x00200000, /// EnticePluginInfo flag: A plugin sets this if it can be unloaded safely while Entice continues to run. 
     2278     
     2279    /// Mask of all bits that indicate a unique feature. 
     2280    MASK_PLUGIN_UNIQUE_FEATURES = PLUGIN_PROJECT_COMPILE 
     2281        | PLUGIN_PROJECT_LIST 
     2282        | PLUGIN_CODECOMPLETION 
     2283        | PLUGIN_CODELAYOUTTAB 
     2284        , 
     2285     
    22312286} 
    22322287 
     
    22442299    } 
    22452300     
    2246     auto loadproc = cast(EnticePluginLoadProc)getPluginProcAddr(hmod, "enticePluginLoad", 1); 
    2247     if(!loadproc) 
     2301    auto infoproc = cast(EnticePluginInfoProc)getPluginProcAddr(hmod, "enticePluginInfo", 1); 
     2302    if(!infoproc) 
     2303        infoproc = cast(EnticePluginInfoProc)getPluginProcAddr(hmod, "enticePluginLoad", 1); 
     2304    if(!infoproc) 
    22482305    { 
    22492306        FreeLibrary(hmod); 
     
    22612318    try 
    22622319    { 
    2263         switch(loadproc(&ep)) 
     2320        switch(infoproc(&ep)) 
    22642321        { 
    22652322            case 0: 
     
    23342391    { 
    23352392        if(modalPlugin) 
     2393        { 
     2394            FreeLibrary(hmod); 
     2395            errnum = 10; 
    23362396            return "Unable to load plugin; already a modal plugin"; 
     2397        } 
    23372398    } 
    23382399     
     
    23402401    { 
    23412402        if(codeLayoutTabPlugin) 
     2403        { 
     2404            FreeLibrary(hmod); 
     2405            errnum = 10; 
    23422406            return "Unable to load plugin; already a code layout tab plugin"; 
     2407        } 
    23432408    } 
    23442409     
  • trunk/win32/entice/projectmanager.d

    r101 r102  
    99{ 
    1010    char[] name; 
     11    EProject project; 
    1112     
    1213    // null if cannot contain sub entries. 
     
    9192            { 
    9293                EProjectEntry pe; 
     94                pe.project = this; 
    9395                //pe.name = std.path.join(projectName, de.name); 
    9496                pe.name = de.name.dup; 
     
    109111            { 
    110112                EProjectEntry pe; 
     113                pe.project = tthis.project; 
    111114                pe.name = std.path.join(tthis.name, de.name); 
    112115                if(de.isdir()) 
  • trunk/win32/entice/proppanel.d

    r101 r102  
    671671                    this.clientSize.width - TEXT_PADDING * 2, 13), tfmtTitle); 
    672672                 
    673                 char[] infotxt; 
    674                 infotxt = info; 
    675                 if(!info.length) 
    676                     infotxt = "No information provided."; 
    677                  
    678                 ea.graphics.drawText(infotxt, this.font, this.foreColor, Rect(TEXT_PADDING, INFO_TEXT_OFFSET_Y, 
    679                     this.clientSize.width - TEXT_PADDING * 2, this.clientSize.height - INFO_TEXT_OFFSET_Y - TEXT_PADDING * 2), 
    680                     tfmtInfo); 
     673                if(info.length) 
     674                { 
     675                    ea.graphics.drawText(info, this.font, this.foreColor, Rect(TEXT_PADDING, INFO_TEXT_OFFSET_Y, 
     676                        this.clientSize.width - TEXT_PADDING * 2, this.clientSize.height - INFO_TEXT_OFFSET_Y - TEXT_PADDING * 2), 
     677                        tfmtInfo); 
     678                } 
    681679            } 
    682680             
  • trunk/win32/entice/scintilladlex.d

    r101 r102  
    605605        void addItem(ApiEntry* ae) 
    606606        { 
     607            if(ae.flags & ApiFlags.PRIVATE) 
     608                return; 
     609            if(ae.flags & ApiFlags.UNDOCUMENTED) 
     610                return; 
     611             
    607612            char[] aename; 
    608613            aename = ae.name; // cache 
     
    18981903     
    18991904     
     1905    bool findBraceMatch(out int istart, out int iend) 
     1906    { 
     1907        bit again = true; 
     1908        istart = sendEditor(SCI_GETCURRENTPOS); 
     1909        if(!istart) 
     1910            again = false; 
     1911        else 
     1912            istart--; 
     1913        iend = sendEditor(SCI_BRACEMATCH, istart); 
     1914        if(-1 != iend) 
     1915        { 
     1916            return true; 
     1917        } 
     1918        else 
     1919        { 
     1920            if(again) 
     1921            { 
     1922                again = false; 
     1923                istart++; 
     1924                iend = sendEditor(SCI_BRACEMATCH, istart); 
     1925                if(-1 != iend) 
     1926                { 
     1927                    return true; 
     1928                } 
     1929            } 
     1930        } 
     1931        return false; 
     1932    } 
     1933     
     1934     
    19001935    // Called when WM_NOTIFY is sent to the parent for this control. 
    19011936    /+ package +/ final void notified(inout Message m) 
     
    19111946            case SCN_UPDATEUI: 
    19121947                { 
    1913                     bit again = true; 
     1948                     
    19141949                    int istart, iend; 
    1915                     istart = sendEditor(SCI_GETCURRENTPOS); 
    1916                     if(!istart) 
    1917                         again = false; 
    1918                     else 
    1919                         istart--; 
    1920                     iend = sendEditor(SCI_BRACEMATCH, istart); 
    1921                     if(-1 != iend) 
     1950                    if(findBraceMatch(istart, iend)) 
    19221951                    { 
    1923                         found_match_brace: 
    19241952                        sendEditor(SCI_BRACEHIGHLIGHT, istart, iend); 
    19251953                         
     
    19341962                    else 
    19351963                    { 
    1936                         if(again) 
    1937                         { 
    1938                             again = false; 
    1939                             istart++; 
    1940                             iend = sendEditor(SCI_BRACEMATCH, istart); 
    1941                             if(-1 != iend) 
    1942                                 goto found_match_brace; 
    1943                         } 
    1944                          
    19451964                        // Clear. 
    19461965                        sendEditor(SCI_BRACEHIGHLIGHT, -1, -1); 
     
    25932612        needScan = false; // Done! No need to re-scan! 
    25942613         
    2595         sendEditor(SCI_EMPTYUNDOBUFFER); // Since it can't be undone yet... 
     2614        version(ENTICE_DESIGNUNDO) 
     2615        { 
     2616        } 
     2617        else 
     2618        { 
     2619            sendEditor(SCI_EMPTYUNDOBUFFER); // Since it can't be undone. 
     2620        } 
    25962621         
    25972622        /+ 
     
    26012626        } 
    26022627        +/ 
     2628    } 
     2629     
     2630     
     2631    final void beginDesignUpdate() 
     2632    { 
     2633        version(ENTICE_DESIGNUNDO) 
     2634        { 
     2635            sendEditor(SCI_BEGINUNDOACTION); 
     2636        } 
     2637    } 
     2638     
     2639     
     2640    final void endDesignUpdate() 
     2641    { 
     2642        version(ENTICE_DESIGNUNDO) 
     2643        { 
     2644            sendEditor(SCI_ENDUNDOACTION); 
     2645        } 
    26032646    } 
    26042647     
     
    28692912        needScan = true; 
    28702913         
    2871         sendEditor(SCI_EMPTYUNDOBUFFER); // Since it can't be undone yet... 
     2914        version(ENTICE_DESIGNUNDO) 
     2915        { 
     2916        } 
     2917        else 
     2918        { 
     2919            sendEditor(SCI_EMPTYUNDOBUFFER); // Since it can't be undone. 
     2920        } 
    28722921    } 
    28732922     
  • trunk/win32/entice/scistyles.d

    r101 r102  
    44 
    55private import std.string, std.ctype, std.conv; 
    6 private import dfl.all, dfl.winapi; 
     6private import dfl.all, dfl.internal.winapi; 
    77private import dfl.scintilla, dfl.cpp.scintilla, dfl.cpp.scilexer; 
    88private import util, drawing; 
  • trunk/win32/entice/startpage.d

    r101 r102  
    99    std.gc, std.utf, std.stdint; 
    1010 
    11 private import dfl.all, dfl.winapi, dfl.utf; 
     11private import dfl.all, dfl.internal.winapi, dfl.internal.utf; 
    1212private import dfl.scintilla, dfl.cpp.scintilla, dfl.cpp.scilexer; 
    1313 
     
    2323import ddprojectmanager, projectmanager; 
    2424 
     25import compile, firstsetupstartpagepanel; 
     26 
    2527import rgroup; 
    2628 
     
    108110     
    109111    int addStartPage() 
    110     in 
    111112    { 
    112113        //assert(showStartPage); // NO... user must have manually requested it. 
    113114        //assert(!startPageClosed); 
    114     } 
    115     body 
    116     { 
     115         
    117116        skipStartPage = false; 
    118117        getStartPage(); // Create startent. 
     
    143142     
    144143     
    145     class StartPageLabel: Label 
     144    class StartPageLabel: Panel //: Label 
    146145    { 
    147146        const char[] FONT_NAME = "Tahoma"; 
     
    158157        char[] tipFileName; 
    159158        bool clickMoreTips = true; 
     159         
     160        FirstSetupStartPagePanel fsspp; 
    160161         
    161162         
     
    194195            stepZEROfmt = TextFormat.genericDefault; 
    195196            stepZEROfmt.formatFlags = stepZEROfmt.formatFlags & ~TextFormatFlags.WORD_BREAK; 
     197             
     198            /*{ 
     199                struct imp { public import dlangselectorpanel; } 
     200                auto panel = new imp.DLangSelectorPanel(); 
     201                panel.backColor = SystemColors.control; 
     202                panel.foreColor = SystemColors.controlText; 
     203                panel.location = Point(10, 300); 
     204                panel.parent = this; 
     205            }*/ 
     206             
     207            setStyle(ControlStyles.ALL_PAINTING_IN_WM_PAINT | ControlStyles.USER_PAINT, true); 
    196208        } 
    197209         
     
    207219        protected override void onPaintBackground(PaintEventArgs ea) 
    208220        { 
    209             //super.onPaintBackground(ea); 
     221            super.onPaintBackground(ea); 
    210222        } 
    211223         
     
    245257         
    246258         
    247         const int TIPS_TOP = 180; 
    248         const int TIPS_HEIGHT = 140
     259        const int TIPS_TOP = 110; 
     260        const int TIPS_HEIGHT = 32
    249261         
    250262         
     
    504516                    curTip = loadRandomLine(tipFileName, false); 
    505517                    if(parent) 
    506                         parent.invalidate(Rect(0, TIPS_TOP - 30, this.clientSize.width, TIPS_HEIGHT + 60), true); 
    507                 } 
    508             } 
     518                        parent.invalidate(Rect(0, TIPS_TOP - 30, this.clientSize.width + 80, TIPS_HEIGHT + 60), true); 
     519                } 
     520            } 
     521             
    509522        } 
    510523         
     
    591604        EProjectControl proj; 
    592605         
     606        FirstSetupStartPagePanel fsspp = null; 
     607         
    593608         
    594609        // IHasEProjectControl 
     
    718733                propInfo.setInfo("Recently Used Files", "Double click on a file from the above list to open it."); 
    719734            } 
     735             
     736            _compilercheck(); 
     737        } 
     738         
     739         
     740        private void _compilercheck() 
     741        { 
     742            if(isCompilerSetup()) 
     743            { 
     744                if(fsspp) 
     745                { 
     746                    fsspp.dispose(); 
     747                    fsspp = null; 
     748                } 
     749            } 
     750            else 
     751            { 
     752                if(!fsspp) 
     753                { 
     754                    string thiscompilerpath = ""; 
     755                    foreachLocateDMD( 
     756                        (string path) 
     757                        { 
     758                            // Just get first one (if any). 
     759                            thiscompilerpath = path; 
     760                            return false; // Break. 
     761                        }); 
     762                    fsspp = new FirstSetupStartPagePanel(thiscompilerpath); 
     763                    fsspp.backColor = SystemColors.control; 
     764                    fsspp.foreColor = SystemColors.controlText; 
     765                    fsspp.location = Point(10, 150); 
     766                    fsspp.parent = ctrl; 
     767                } 
     768            } 
    720769        } 
    721770         
  • trunk/win32/entice/tabber.d

    r101 r102  
    22// See the included enticesourcelicense.txt for copyright and license details. 
    33 
    4  
    5 private import dfl.all, dfl.winapi; 
     4// Tab detaching hasn't been fully tested. 
     5 
     6version(TABBER_SIMPLE) 
     7
     8    version = TABBER_NO_DETACH; 
     9    version = TABBER_NO_FIT_TEXT; 
     10
     11 
     12 
     13private import dfl.all, dfl.internal.winapi; 
    614 
    715 
     
    2129    } 
    2230     
     31    this(char[] text, bool detached) 
     32    { 
     33        _txt = text; 
     34        version(TABBER_NO_DETACH) 
     35        { 
     36            if(detached) 
     37                throw new Exception("Cannot detach this tab"); 
     38        } 
     39        else 
     40        { 
     41            _detached = detached; 
     42        } 
     43    } 
     44     
    2345     
    2446    final char[] text() // getter 
     
    4062     
    4163     
    42     // Called whenever this tab should be hidden. 
    43     // It is also called before removing it from the Tabber. 
    44     // If this function throws an exception, the removal will fail. 
     64    final bool detached() // getter 
     65    { 
     66        return _detached; 
     67    } 
     68     
     69     
     70    /// Called whenever this tab should be hidden. 
     71    /// It is also called before removing it from the Tabber. 
     72    /// If this function throws an exception, the removal will fail. 
    4573    void onHide(Tabber tabc, int index) 
    4674    { 
     
    4876     
    4977     
    50     // Called when this tab should be shown. 
    51     // It is also called after adding it to the Tabber. 
     78    /// Called when this tab should be shown. 
     79    /// It is also called after adding it to the Tabber. 
    5280    void onShow(Tabber tabc, int index) 
     81    { 
     82    } 
     83     
     84     
     85    /// Called when this tab is being detached. 
     86    /// This is also called when a detached tab is added. 
     87    void onDetach(Tabber tabc, int index) 
     88    { 
     89    } 
     90     
     91     
     92    /// Called when this tab is being re-attached. 
     93    /// This is also called when an attached tab is added. 
     94    void onAttach(Tabber tabc, int index) 
    5395    { 
    5496    } 
     
    59101    Object _tag = null; 
    60102    int _width = 0; // Includes padding, so 0 is uninitialized. 
     103    version(TABBER_NO_DETACH) 
     104        const bool _detached = false; 
     105    else 
     106        bool _detached = false; 
    61107} 
    62108 
     
    67113    { 
    68114        setStyle(ControlStyles.CONTAINER_CONTROL, true); 
     115        //setStyle(ControlStyles.ALL_PAINTING_IN_WM_PAINT | ControlStyles.USER_PAINT, true); 
    69116         
    70117        calcTheight(); 
     
    227274    { 
    228275        return _allowuserdrag; 
     276    } 
     277     
     278     
     279    final bool detachTab(int index) 
     280    { 
     281        version(TABBER_NO_DETACH) 
     282        { 
     283            throw new Exception("Cannot detach this tab"); 
     284        } 
     285        else 
     286        { 
     287            if(!_tabs[index]._detached) 
     288            { 
     289                _tabs[index]._detached = true; 
     290                if(index != selidx) 
     291                { 
     292                    showing(_tabs[index], index); 
     293                } 
     294                 
     295                if(index == selidx) 
     296                { 
     297                    selTabGone(); 
     298                     
     299                    onSelectedIndexAffected(EventArgs.empty); 
     300                    if(-1 != selidx) // Can happen. 
     301                        showing(_tabs[selidx], selidx); 
     302                } 
     303                 
     304                _tabs[index].onDetach(this, index); 
     305                 
     306                if(isHandleCreated) 
     307                { 
     308                    recalcTabs(); 
     309                     
     310                    redrawTabs(); 
     311                } 
     312                 
     313                return true; 
     314            } 
     315        } 
     316        return false; 
     317    } 
     318     
     319     
     320    final bool attachTab(int index) 
     321    { 
     322        version(TABBER_NO_DETACH) 
     323        { 
     324        } 
     325        else 
     326        { 
     327            if(_tabs[index]._detached) 
     328            { 
     329                _tabs[index]._detached = false; 
     330                if(-1 == selidx) 
     331                { 
     332                    selidx = index; 
     333                    onSelectedIndexAffected(EventArgs.empty); 
     334                } 
     335                if(index != selidx) 
     336                { 
     337                    hiding(_tabs[index], index); 
     338                } 
     339                 
     340                _tabs[index].onAttach(this, index); 
     341                 
     342                if(isHandleCreated) 
     343                { 
     344                    recalcTabs(); 
     345                     
     346                    redrawTabs(); 
     347                } 
     348                 
     349                return true; 
     350            } 
     351        } 
     352        return false; 
    229353    } 
    230354     
     
    247371        onTabAdded(ea); 
    248372         
    249         if(1 == _tabs.length) 
    250         { 
    251             assert(!i); 
    252             selidx = 0; 
    253              
    254             onSelectedIndexAffected(EventArgs.empty); 
    255             showing(t, 0); //showing(_tabs[0], i); 
     373        if(-1 == selidx) 
     374        { 
     375            if(!t._detached) 
     376            { 
     377                selidx = i; 
     378                onSelectedIndexAffected(EventArgs.empty); 
     379                showing(t, i); 
     380            } 
    256381        } 
    257382        else if(i <= selidx) 
     
    262387        } 
    263388         
    264         if(isHandleCreated) 
     389        if(t._detached) 
     390            _tabs[i].onDetach(this, i); 
     391        else 
     392            _tabs[i].onAttach(this, i); 
     393         
     394        if(t._detached) 
     395        { 
     396            showing(t, i); 
     397        } 
     398         
     399        if(isHandleCreated && !t._detached) 
    265400        { 
    266401            recalcTabs(); 
     
    276411    { 
    277412        return insertTab(i, new Tab(text)); 
     413    } 
     414     
     415     
     416    private void selTabGone() 
     417    { 
     418        // Current tab is gone so make sure newly selected one isn't detached. 
     419        // Check current or scan back to find non-detached tab. 
     420        bool foundgoodtab = false; 
     421        for(int i = selidx; i >= 0; i--) 
     422        { 
     423            if(!_tabs[i]._detached) 
     424            { 
     425                selidx = i; 
     426                foundgoodtab = true; 
     427                break; 
     428            } 
     429        } 
     430        if(!foundgoodtab) 
     431        { 
     432            // No non-detached ones before, so look after. 
     433            for(int i = selidx + 1; i < _tabs.length; i++) 
     434            { 
     435                if(!_tabs[i]._detached) 
     436                { 
     437                    selidx = i; 
     438                    foundgoodtab = true; 
     439                    break; 
     440                } 
     441            } 
     442            if(!foundgoodtab) 
     443            { 
     444                // No non-detached tabs, no selection. 
     445                selidx = -1; 
     446            } 
     447        } 
    278448    } 
    279449     
     
    287457         
    288458        Tab rtab = _tabs[index]; 
    289         if(selaff
     459        if(selaff || rtab._detached
    290460        { 
    291461            hiding(rtab, index); 
     
    316486        } 
    317487         
     488        if(selaff) 
     489        { 
     490            selTabGone(); 
     491        } 
     492         
    318493        scope ea = new TabEventArgs(rtab); 
    319494        onTabRemoved(ea); 
     
    326501        } 
    327502         
    328         if(isHandleCreated
     503        if(isHandleCreated && !rtab._detached
    329504        { 
    330505            recalcTabs(); 
     
    337512    final void replaceAllTabs(Tab[] newTabs, int newSelectedIndex = -1) 
    338513    { 
    339         bool selaff = false; 
    340         if(_tabs.length) 
    341         { 
    342             assert(-1 != selidx); 
    343             selaff = true; 
    344             hiding(_tabs[selidx], selidx); 
     514        bool selaff = -1 != selidx; 
     515        for(int i = 0; i < _tabs.length; i++) 
     516        { 
     517            if(selidx == i || _tabs[i]._detached) 
     518            { 
     519                hiding(_tabs[i], i); 
     520            } 
    345521        } 
    346522         
     
    359535            _tabs = newTabs; 
    360536             
    361             //assert(newSelectedIndex >= 0); 
    362             //assert(newSelectedIndex < newTabs.length); 
    363537            if(newSelectedIndex < 0 || newSelectedIndex >= newTabs.length) 
    364                 newSelectedIndex = 0; 
     538            { 
     539                // No explicit selection set. 
     540                // Default select first non-detached tab. 
     541                // If all detached, leave -1 
     542                newSelectedIndex = -1; 
     543                for(int i = 0; i < _tabs.length; i++) 
     544                { 
     545                    if(!_tabs[i]._detached) 
     546                    { 
     547                        newSelectedIndex = i; 
     548                        break; 
     549                    } 
     550                } 
     551            } 
    365552            selidx = newSelectedIndex; 
    366             selaff = true; 
    367             showing(_tabs[selidx], selidx); 
     553            if(-1 != selidx) 
     554            { 
     555                selaff = true; 
     556                showing(_tabs[selidx], selidx); 
     557            } 
     558             
     559            // Show all detached tabs. 
     560            // Not selidx in case user selected a detached one, 
     561            // it would be shown above already. 
     562            for(int i = 0; i < _tabs.length; i++) 
     563            { 
     564                if(_tabs[i]._detached && i != selidx) 
     565                { 
     566                    showing(_tabs[i], i); 
     567                } 
     568            } 
    368569        } 
    369570         
     
    393594        _tabs[i]._txt = newText; 
    394595         
    395         if(isHandleCreated
     596        if(isHandleCreated && !_tabs[i].detached
    396597        { 
    397598            recalcTabs(); 
     
    447648     
    448649     
    449     version(TABBER_SIMPLE
     650    version(TABBER_NO_FIT_TEXT
    450651    { 
    451652        private void recalcTabs() 
    452         in 
    453653        { 
    454654            assert(isHandleCreated); 
    455         } 
    456         body 
    457         { 
     655             
    458656            Graphics g; 
    459657            g = createGraphics(); 
     
    461659            foreach(Tab t; _tabs) 
    462660            { 
    463                 tab._width = calcTextWidth(g, t.text) + TAB_PADDING * 2; 
     661                if(t._detached) 
     662                { 
     663                    tab._width = 0; 
     664                } 
     665                else 
     666                { 
     667                    tab._width = calcTextWidth(g, t.text) + TAB_PADDING * 2; 
     668                } 
    464669            } 
    465670             
     
    470675    { 
    471676        private void recalcTabs() 
    472         in 
    473677        { 
    474678            assert(isHandleCreated); 
    475         } 
    476         body 
    477         { 
     679             
    478680            if(!_tabs.length || !clientSize.width) 
    479681                return; 
     
    487689            foreach(Tab t; _tabs) 
    488690            { 
    489                 t._width = calcTextWidth(g, t.text) + TAB_PADDING * 2; 
    490                  
    491                 x += t._width + TAB_PADDING; 
     691                if(t._detached) 
     692                { 
     693                    t._width = 0; 
     694                } 
     695                else 
     696                { 
     697                    t._width = calcTextWidth(g, t.text) + TAB_PADDING * 2; 
     698                     
     699                    x += t._width + TAB_PADDING; 
     700                } 
    492701            } 
    493702             
     
    502711                foreach(Tab t; _tabs) 
    503712                { 
    504                     if(t._width > aw) 
     713                    //if(!t._detached) // Detached t._width is always 0 for next comparison. 
    505714                    { 
    506                         int less; 
    507                         less = t._width - aw; // Take away the excess of the above average. 
    508                          
    509                         t._width -= less; // Smaller tab. 
    510                          
    511                         x -= less; // For next trip around. 
     715                        if(t._width > aw) 
     716                        { 
     717                            int less; 
     718                            less = t._width - aw; // Take away the excess of the above average. 
     719                             
     720                            t._width -= less; // Smaller tab. 
     721                             
     722                            x -= less; // For next trip around. 
     723                        } 
    512724                    } 
    513725                } 
     
    524736    final void getAllTabRects(void delegate(int index, inout Rect tabRect) callback) 
    525737    { 
    526         //Rect getTabsRect() 
    527738        Rect r, tabRect; 
    528739        r = getTabsRect(); 
    529          
     740        // Using position -1 for detached tabs, 
     741        // this way the point doesn't match with other tabs (e.g. findTabFromPoint) 
    530742        if(tright) 
    531743        { 
     
    533745            foreach_reverse(int i, Tab tab; _tabs) 
    534746            { 
    535                 r.x -= tab._width + TAB_PADDING; 
    536                  
    537                 tabRect.x = r.x; 
    538                 tabRect.y = r.y; 
    539                 tabRect.width = tab._width; 
    540                 tabRect.height = r.height; 
    541                  
     747                if(tab._detached) 
     748                { 
     749                    tabRect = Rect(-1, 0, 0, 0); 
     750                } 
     751                else 
     752                { 
     753                    r.x -= tab._width + TAB_PADDING; 
     754                    tabRect.x = r.x; 
     755                    tabRect.y = r.y; 
     756                    tabRect.width = tab._width; 
     757                    tabRect.height = r.height; 
     758                } 
    542759                callback(i, tabRect); 
    543760            } 
     
    547764            foreach(int i, Tab tab; _tabs) 
    548765            { 
    549                 tabRect.x = r.x; 
    550                 tabRect.y = r.y; 
    551                 tabRect.width = tab._width; 
    552                 tabRect.height = r.height; 
    553                  
     766                if(tab._detached) 
     767                { 
     768                    tabRect = Rect(-1, 0, 0, 0); 
     769                } 
     770                else 
     771                { 
     772                    tabRect.x = r.x; 
     773                    tabRect.y = r.y; 
     774                    tabRect.width = tab._width; 
     775                    tabRect.height = r.height; 
     776                    r.x += tabRect.width + TAB_PADDING; 
     777                } 
    554778                callback(i, tabRect); 
    555                  
    556                 r.x += tabRect.width + TAB_PADDING; 
    557779            } 
    558780        } 
     
    561783     
    562784    final void getAllTabRects(Rect[] buf) 
    563     in 
    564785    { 
    565786        assert(buf.length >= _tabs.length); 
    566     } 
    567     body 
    568     { 
     787         
    569788        getAllTabRects( 
    570789            (int i, inout Rect r) 
     
    702921                (int i, inout Rect tabRect) 
    703922                { 
     923                    if(_tabs[i].detached) 
     924                        return; 
    704925                    txt = _tabs[i].text; 
    705926                    tw = tabRect.width - TAB_PADDING * 2; 
     
    9741195                                 
    9751196                                auto newtabs = _tabs.dup; 
     1197                                int imovebegin, imoveend; 
    9761198                                if(iovernow > _userMovingTab) 
    9771199                                { 
     1200                                    imovebegin = _userMovingTab; 
     1201                                    imoveend = iovernow; 
    9781202                                    for(auto mi = _userMovingTab; mi != iovernow; mi++) 
    9791203                                    { 
     
    9851209                                else //if(_userMovingTab > iovernow) 
    9861210                                { 
     1211                                    imovebegin = iovernow; 
     1212                                    imoveend = _userMovingTab; 
    9871213                                    for(auto mi = _userMovingTab; mi != iovernow; mi--) 
    9881214                                    { 
     
    9971223                                selidx = _userMovingTab; // ! 
    9981224                                 
    999                                 //invalidate(getTabsRect(), false); // Not good enough; doesn't fix the line under the tabs. 
    1000                                 invalidate(Rect(0, tbottom ? (clientSize.height - theight) : 0, getTabsRect().width + 4, theight), false); 
     1225                                // Whole bar: 
     1226                                //invalidate(Rect(0, tbottom ? (clientSize.height - theight) : 0, getTabsRect().width + 4, theight), false); 
     1227                                // Just the tabs involved in the move: 
     1228                                { 
     1229                                    int movebeginx = 0, movewidth = 0; 
     1230                                    getAllTabRects( 
     1231                                        (int i, inout Rect tabRect) 
     1232                                        { 
     1233                                            if(i == imovebegin) 
     1234                                            { 
     1235                                                movebeginx = tabRect.x; 
     1236                                            } 
     1237                                            if(i >= imovebegin && i <= imoveend) 
     1238                                            { 
     1239                                                movewidth += tabRect.width; 
     1240                                            } 
     1241                                        }); 
     1242                                    invalidate(Rect(movebeginx - 6, tbottom ? (clientSize.height - theight) : 0, movewidth + 6 + 6, theight), false); 
     1243                                } 
    10011244                                 
    10021245                                scope udea = new TabIndexEventArgs(_userMovingTab, tabs[_userMovingTab]); 
     
    11171360     
    11181361    private void redrawTabs() 
    1119     in 
    11201362    { 
    11211363        assert(isHandleCreated); 
    1122     } 
    1123     body 
    1124     { 
     1364         
    11251365        Rect r; 
    11261366         
     
    14111651{ 
    14121652    this(int fromIndex, int toIndex) 
    1413     in 
    14141653    { 
    14151654        assert(fromIndex >= 0); 
    14161655        assert(toIndex >= 0); 
    1417     } 
    1418     body 
    1419     { 
     1656         
    14201657        this._fromindex = fromIndex; 
    14211658        this._toindex = toIndex; 
     
    14391676} 
    14401677 
     1678 
     1679class DetachedTabForm: Form 
     1680{ 
     1681    this() 
     1682    { 
     1683        clientSize = Size(500, 400); 
     1684    } 
     1685     
     1686     
     1687    this(Tabber tabc, Tab tab) 
     1688    { 
     1689        this(); 
     1690        text = tab.text; 
     1691        if(!tab._detached) 
     1692            throw new Exception("Tab is not detached"); 
     1693        debug 
     1694        { 
     1695            if(-1 == tabc.findTab(tab)) 
     1696                throw new Exception("Tab not found"); 
     1697        } 
     1698        version(TABBER_NO_DETACH) 
     1699        { 
     1700        } 
     1701        else 
     1702        { 
     1703            this.tabc = tabc; 
     1704            this.tab = tab; 
     1705        } 
     1706    } 
     1707     
     1708     
     1709    version(TABBER_NO_DETACH) 
     1710    { 
     1711    } 
     1712    else 
     1713    { 
     1714         
     1715        override void onClosing(CancelEventArgs ea) 
     1716        { 
     1717            super.onClosing(ea); 
     1718             
     1719            if(!ea.cancel) 
     1720            { 
     1721                int ti = tabc.findTab(tab); 
     1722                if(-1 != ti) 
     1723                    tabc.attachTab(ti); 
     1724            } 
     1725        } 
     1726         
     1727         
     1728        private Tabber tabc; 
     1729        private Tab tab; 
     1730         
     1731    } 
     1732     
     1733} 
     1734 
  • trunk/win32/entice/toolbox.d

    r101 r102  
    55private import std.string; 
    66 
    7 private import dfl.all, dfl.winapi; 
     7private import dfl.all, dfl.internal.winapi; 
    88 
    99private import dfldesigner, design; 
     
    514514    // Only the pointer tool gets a null type name. 
    515515    this(Icon icon, char[] typeName, char[] toolName) 
    516     in 
    517516    { 
    518517        assert(toolName.length); 
    519     } 
    520     body 
    521     { 
     518         
    522519        _icon = icon; 
    523520        _typeName = typeName; 
     
    528525     
    529526    this(Icon icon, char[] typeName) 
    530     in 
    531527    { 
    532528        assert(typeName.length); 
    533     } 
    534     body 
    535     { 
     529         
    536530        int i; 
    537531        i = std.string.rfind(typeName, '.'); 
  • trunk/win32/entice/usercomment.d

    r101 r102  
    55import std.string; 
    66 
    7 private import dfl.all, dfl.winapi; 
     7private import dfl.all, dfl.internal.winapi; 
    88 
    99import dfldesigner, resource; 
     
    334334        commentGroup.name = "commentGroup"; 
    335335        commentGroup.text = "Send Application Developers a Comment About:"; 
    336         commentGroup.bounds = dfl.base.Rect(8, 40, 520, 312); 
     336        commentGroup.bounds = dfl.all.Rect(8, 40, 520, 312); 
    337337        commentGroup.parent = this; 
    338338        //~DFL dfl.button.RadioButton=likeRadio 
     
    341341        likeRadio.text = "Something you &like"; 
    342342        likeRadio.checkState = dfl.button.CheckState.CHECKED; 
    343         likeRadio.bounds = dfl.base.Rect(28, 17, 283, 23); 
     343        likeRadio.bounds = dfl.all.Rect(28, 17, 283, 23); 
    344344        likeRadio.parent = commentGroup; 
    345345        //~DFL dfl.button.RadioButton=hateRadio 
     
    347347        hateRadio.name = "hateRadio"; 
    348348        hateRadio.text = "Something you &dislike"; 
    349         hateRadio.bounds = dfl.base.Rect(28, 41, 283, 23); 
     349        hateRadio.bounds = dfl.all.Rect(28, 41, 283, 23); 
    350350        hateRadio.parent = commentGroup; 
    351351        //~DFL dfl.button.RadioButton=bugRadio 
     
    353353        bugRadio.name = "bugRadio"; 
    354354        bugRadio.text = "An improper &behavior of this application"; 
    355         bugRadio.bounds = dfl.base.Rect(28, 65, 283, 23); 
     355        bugRadio.bounds = dfl.all.Rect(28, 65, 283, 23); 
    356356        bugRadio.parent = commentGroup; 
    357357        //~DFL dfl.button.RadioButton=requestRadio 
     
    359359        requestRadio.name = "requestRadio"; 
    360360        requestRadio.text = "A new &feature you desire"; 
    361         requestRadio.bounds = dfl.base.Rect(28, 89, 283, 23); 
     361        requestRadio.bounds = dfl.all.Rect(28, 89, 283, 23); 
    362362        requestRadio.parent = commentGroup; 
    363363        //~DFL dfl.textbox.TextBox=commentBox 
     
    369369        commentBox.acceptsReturn = true; 
    370370        commentBox.scrollBars = dfl.base.ScrollBars.VERTICAL; 
    371         commentBox.bounds = dfl.base.Rect(12, 116, 496, 184); 
     371        commentBox.bounds = dfl.all.Rect(12, 116, 496, 184); 
    372372        commentBox.parent = commentGroup; 
    373373        //~DFL dfl.label.Label=topLabel 
     
    375375        topLabel.name = "topLabel"; 
    376376        topLabel.text = "Please provide a brief opinion of %s so that we will be able to improve your user experience. Positive and negative comments are welcome. Bug reports are especially helpful."; 
    377         topLabel.bounds = dfl.base.Rect(8, 8, 520, 32); 
     377        topLabel.bounds = dfl.all.Rect(8, 8, 520, 32); 
    378378        topLabel.parent = this; 
    379379        //~DFL dfl.button.Button=emailBtn 
     
    381381        emailBtn.name = "emailBtn"; 
    382382        emailBtn.text = "&E-mail Address..."; 
    383         emailBtn.bounds = dfl.base.Rect(8, 360, 115, 23); 
     383        emailBtn.bounds = dfl.all.Rect(8, 360, 115, 23); 
    384384        emailBtn.parent = this; 
    385385        //~DFL dfl.button.Button=sendBtn 
     
    388388        sendBtn.enabled = false; 
    389389        sendBtn.text = "&Send Comment"; 
    390         sendBtn.bounds = dfl.base.Rect(336, 360, 107, 23); 
     390        sendBtn.bounds = dfl.all.Rect(336, 360, 107, 23); 
    391391        sendBtn.parent = this; 
    392392        //~DFL dfl.button.Button=cancelBtn 
     
    394394        cancelBtn.name = "cancelBtn"; 
    395395        cancelBtn.text = "Cancel"; 
    396         cancelBtn.bounds = dfl.base.Rect(456, 360, 75, 23); 
     396        cancelBtn.bounds = dfl.all.Rect(456, 360, 75, 23); 
    397397        cancelBtn.parent = this; 
    398398        //~Entice Designer 0.8pre5 code ends here. 
  • trunk/win32/entice/usercommentemail.d

    r101 r102  
    8181        preface.name = "preface"; 
    8282        preface.text = "Please provide your &e-mail address so that we may contact you in response to your comment if needed. We will not contact you for any other reason and your e-mail address will not be sold or given away. However, you do not need to provide your e-mail address for anonymous comments."; 
    83         preface.bounds = dfl.base.Rect(8, 8, 288, 69); 
     83        preface.bounds = dfl.all.Rect(8, 8, 288, 69); 
    8484        preface.parent = this; 
    8585        //~DFL dfl.textbox.TextBox=emailBox 
     
    8787        emailBox.name = "emailBox"; 
    8888        emailBox.maxLength = 500; 
    89         emailBox.bounds = dfl.base.Rect(8, 80, 288, 23); 
     89        emailBox.bounds = dfl.all.Rect(8, 80, 288, 23); 
    9090        emailBox.parent = this; 
    9191        //~DFL dfl.button.Button=okBtn 
     
    9393        okBtn.name = "okBtn"; 
    9494        okBtn.text = "OK"; 
    95         okBtn.bounds = dfl.base.Rect(144, 112, 75, 23); 
     95        okBtn.bounds = dfl.all.Rect(144, 112, 75, 23); 
    9696        okBtn.parent = this; 
    9797        //~DFL dfl.button.Button=cancelBtn 
     
    9999        cancelBtn.name = "cancelBtn"; 
    100100        cancelBtn.text = "Cancel"; 
    101         cancelBtn.bounds = dfl.base.Rect(224, 112, 75, 23); 
     101        cancelBtn.bounds = dfl.all.Rect(224, 112, 75, 23); 
    102102        cancelBtn.parent = this; 
    103103        //~DFL dfl.button.Button=clearBtn 
     
    105105        clearBtn.name = "clearBtn"; 
    106106        clearBtn.text = "Clear"; 
    107         clearBtn.bounds = dfl.base.Rect(8, 112, 75, 23); 
     107        clearBtn.bounds = dfl.all.Rect(8, 112, 75, 23); 
    108108        clearBtn.parent = this; 
    109109        //~Entice Designer 0.8pre4 code ends here. 
  • trunk/win32/entice/util.d

    r101 r102  
    66private import dfl.all; 
    77 
    8  
    9 /// Returns: the next word and updates line to exclude it. 
    10 char[] nextWord(inout char[] line) 
    11 
    12     if(!line.length) 
    13         return null; 
    14      
    15     char[] result; 
    16     uint i; 
    17      
    18     for(i = 0; i != line.length; i++) 
    19     { 
    20         if(line[i] == ' ') 
    21         { 
    22             // Found a word. 
    23             result = line[0 .. i]; 
    24             line = line[i + 1 .. line.length]; 
    25             return result; 
    26         } 
    27     } 
    28      
    29     // Fell through, last word. 
    30     result = line; 
    31     line = null; 
    32     return result; 
     8private import dfl.internal.winapi : ShellExecuteA; 
     9 
     10 
     11void resizeCenterForm(Form form, Size size, bool onlyGrow = false) 
     12
     13    int wdiff = size.width - form.clientSize.width; 
     14    int hdiff = size.height - form.clientSize.height; 
     15    if(onlyGrow) 
     16    { 
     17        if(wdiff < 0) 
     18        { 
     19            wdiff = 0; 
     20            size = Size(form.clientSize.width, size.height); 
     21        } 
     22        if(hdiff < 0) 
     23        { 
     24            hdiff = 0; 
     25            size = Size(size.width, form.clientSize.height); 
     26        } 
     27    } 
     28    if(wdiff || hdiff) 
     29    { 
     30        form.bounds = Rect( 
     31            form.left + wdiff / 2, form.top + hdiff / 2, 
     32            size.width, size.height 
     33            ); 
     34        form.clientSize = size; 
     35    } 
     36
     37 
     38 
     39void launchUrl(char[] url) 
     40
     41    if(cast(int)ShellExecuteA(null, "open", myStringz(url), null, null, 0) <= 32) 
     42    { 
     43        msgBox("Unable to open URL"); 
     44    } 
     45     
     46    /+ 
     47    ShellExecuteA(null, "open", "rundll32.exe", 
     48        std.string.toStringz("url.dll,FileProtocolHandler " ~ url), 
     49        null, SW_SHOWDEFAULT); 
     50    +/ 
    3351} 
    3452 
     
    8098    } 
    8199    assert(0); 
    82 } 
    83  
    84  
    85 // s is the string to get modified; rep are char pairs, a char is mapped to the next one. 
    86 char[] replacechars(char[] s, char[] rep ...) 
    87 in 
    88 { 
    89     assert(0 == (rep.length % 2)); 
    90 } 
    91 body 
    92 { 
    93     size_t irep; 
    94     size_t iw; 
    95     char[] result; 
    96     for(iw = 0; iw != s.length; iw++) 
    97     { 
    98         for(irep = 0; irep < rep.length; irep += 2) 
    99         { 
    100             if(s[iw] == rep[irep]) 
    101             { 
    102                 result = s.dup; 
    103                 goto do_rep; 
    104             } 
    105         } 
    106     } 
    107     return s; 
    108     for(; iw != s.length; iw++) 
    109     { 
    110         for(irep = 0; irep < rep.length; irep += 2) 
    111         { 
    112             if(s[iw] == rep[irep]) 
    113             { 
    114                 do_rep: // Jump in with valid iw and irep. 
    115                 result[iw] = rep[irep + 1]; 
    116                 break; 
    117             } 
    118         } 
    119     } 
    120     return result; 
    121 } 
    122  
    123 unittest 
    124 { 
    125     assert("foobar" == replacechars("buuqar", 'u','o', 'q','b', 'b','f')); 
    126     assert("foobar" == replacechars("foobar")); 
    127     assert("foobar" == replacechars("foobar", 'x','y', 'a','a')); 
    128     assert("foobar" == replacechars("foobaz", 'x','y', 'z','r')); 
    129 } 
    130  
    131  
    132 bool startswith(char[] str, char[] swith) 
    133 { 
    134     return swith.length <= str.length && str[0 .. swith.length] == swith; 
    135 } 
    136  
    137 unittest 
    138 { 
    139     assert(startswith("foobar", "foo")); 
    140     assert(startswith("foobar", "f")); 
    141     assert(startswith("foobar", "foobar")); 
    142      
    143     assert(!startswith("foobar", "F")); 
    144     assert(!startswith("foobar", "Foobar")); 
    145     assert(!startswith("foobar", "oobar")); 
    146     assert(!startswith("foobar", "ffoobar")); 
    147     assert(!startswith("foobar", "foobare")); 
    148     assert(!startswith("foobar", "foobarr")); 
    149 } 
    150  
    151  
    152 // s is the string to get modified; rep are string pairs, a string is mapped to the next one. 
    153 char[] replacestrings(char[] s, char[][] rep ...) 
    154 in 
    155 { 
    156     assert(0 == (rep.length % 2)); 
    157 } 
    158 body 
    159 { 
    160     char[] result; 
    161     size_t startiw, iw; 
    162     for(iw = startiw = 0;; iw++) 
    163     { 
    164         at_iw: ; 
    165         if(iw == s.length) 
    166             break; 
    167         for(size_t irep = 0; irep < rep.length; irep += 2) 
    168         { 
    169             if(0 == rep[irep].length) 
    170                 continue; 
    171             if(startswith(s[iw .. $], rep[irep])) 
    172             { 
    173                 if(iw) 
    174                     result ~= s[startiw .. iw]; 
    175                 result ~= rep[irep + 1]; 
    176                 iw += rep[irep].length; 
    177                 startiw = iw; 
    178                 goto at_iw; 
    179             } 
    180         } 
    181     } 
    182     if(0 == startiw) 
    183         return s; 
    184     if(startiw != iw) 
    185         result ~= s[startiw .. $]; 
    186     return result; 
    187 } 
    188  
    189 unittest 
    190 { 
    191     assert("foobar" == replacestrings("foou", "","X", "u","bar")); 
    192     assert("foobar" == replacestrings("foobar", "f","f")); 
    193     assert("foobar" == replacestrings("foobar")); 
    194     assert("foobar" == replacestrings("foobar")); 
    195     assert("foobar" == replacestrings("foobar", "r","r")); 
    196     assert("foobar" == replacestrings("FOOBAR", "FOOBAR","foobar")); 
    197     assert("foobar" == replacestrings("foobar", "bare","X")); 
    198     assert("foobar" == replacestrings("foobar", "F","X")); 
    199     assert("foobar" == replacestrings("buuqar", "u","o", "q","b", "b","f")); 
    200 } 
    201  
    202  
    203 int isEolChar(char ch) 
    204 { 
    205     return '\r' == ch || '\n' == ch; 
    206100} 
    207101 
     
    367261 
    368262 
    369 char* myStringz(char[] s) 
    370 { 
    371     if(!s.length) 
    372         return ""; 
    373      
    374     // Check if already null terminated. 
    375     if(!s.ptr[s.length]) // Disables bounds checking. 
    376         return s.ptr; 
    377      
    378     // Need to duplicate with null terminator. 
    379     char[] result; 
    380     result = new char[s.length + 1]; 
    381     result[s.length] = 0; 
    382     result = result[0 .. s.length]; 
    383     result[] = s; 
    384     return result.ptr; 
    385 } 
    386  
    387  
    388263// Allows you to create a bunch of nesting directories all at once. 
    389264// Make sure -dirpath- does not include a file on the end 
     
    544419 
    545420// Other forms of path joins aren't for "absolute" paths. 
    546 // In those cases (and std.path.join), joining "C:" with "foo.txt" gives "C:foo.txt", 
    547 // this version gives "C:\foo.txt", an appropriate absolute path. 
    548 char[] pathJoinAbsolute(char[] first, char[] second) 
    549 
    550     if(!first.length) 
    551         return second; 
    552     if(!second.length) 
    553         return first; 
    554      
    555     if('/' == first[$ - 1]) 
    556     { 
    557         first_slash: ; 
    558          
    559         if('/' == second[0]) 
    560         { 
    561             firstsecond_slash: ; 
    562             return first ~ second[1 .. $]; 
     421// In those cases (and std.path.join), joining "X:" with "foo.txt" gives "X:foo.txt", 
     422// this version gives "X:\foo.txt", an appropriate absolute path. 
     423// If currentDir is empty, the environment's current directory is used. 
     424char[] pathJoinAbsolute(char[] first, char[] second, string currentDir = null) 
     425
     426    first = getAbsolutePath(first, currentDir); 
     427    return std.path.join(first, second); 
     428
     429 
     430unittest 
     431
     432    string curdir = r"d:\foo"; 
     433    assert(pathJoinAbsolute("", "", curdir) == r"d:\foo"); 
     434    assert(pathJoinAbsolute("bar", "", curdir) == r"d:\foo\bar"); 
     435    assert(pathJoinAbsolute("", "baz", curdir) == r"d:\foo\baz"); 
     436    assert(pathJoinAbsolute("X:", "foo.txt", curdir) == r"X:\foo.txt"); 
     437    assert(pathJoinAbsolute("bar", "baz", curdir) == r"d:\foo\bar\baz"); 
     438
     439 
     440 
     441bool isPathAbsolute(string p) 
     442
     443    version(Windows) 
     444    { 
     445        if(p.length > 2 && p[1] == ':' 
     446            && (p[2] == '\\' || p[2] == '/')) 
     447            return true; 
     448        if(p.length >= 2 && p[0] == '\\' && p[1] == '\\') 
     449            return true; 
     450        return false; 
     451    } 
     452    else 
     453    { 
     454        return p.length && '/' == p[0]; 
     455    } 
     456
     457 
     458 
     459// If currentDir is empty, the environment's current directory is used. 
     460string getAbsolutePath(string p, string currentDir = null) 
     461
     462    if(isPathAbsolute(p)) 
     463        return p; 
     464    if(!currentDir.length) 
     465        currentDir = std.file.getcwd(); 
     466    if(!p.length) 
     467        return currentDir; 
     468    version(Windows) 
     469    { 
     470        if(p.length > 1 && p[1] == ':') 
     471        { 
     472            assert(p.length < 3 || (p[2] != '\\' && p[2] != '/')); 
     473            // Relative to current directory of specified drive. 
     474            // Could use env var "=X:" 
     475            if(currentDir.length > 1 && currentDir[1] == ':') 
     476            { 
     477                //return p[0 .. 2] ~ currentDir[2 .. $] ~ "\\" ~ p[2 .. $]; // Alt. 
     478                // Relative to current directory if current drive. 
     479                // Relative to drive root if not current drive. 
     480                if(rawlower(p[0]) == rawlower(currentDir[0])) 
     481                    return currentDir ~ "\\" ~ p[2 .. $]; 
     482                return p[0 .. 2] ~ "\\" ~ p[2 .. $]; 
     483            } 
     484            throw new Exception("Unexpected current directory: " ~ currentDir); 
     485        } 
     486        else if(p.length > 0 
     487            && (p[0] == '/' || p[0] == '\\')) 
     488        { 
     489            // Relative to current drive. 
     490            if(currentDir.length > 1 && currentDir[1] == ':') 
     491            { 
     492                return currentDir[0 .. 2] ~ p; 
     493            } 
     494            throw new Exception("Unexpected current directory: " ~ currentDir); 
    563495        } 
    564496        else 
    565497        { 
    566             version(Windows) 
    567             { 
    568                 if('\\' == second[0]) 
    569                     goto firstsecond_slash; 
    570             } 
    571              
    572             // First_slash, not firstsecond_slash.. 
    573             return first ~ second; 
     498            return std.path.join(currentDir, p); 
    574499        } 
    575500    } 
    576501    else 
    577502    { 
    578         version(Windows) 
    579         { 
    580             if('\\' == first[$ - 1]) 
    581                 goto first_slash; 
    582         } 
    583          
    584         // Not first_slash.. 
    585         if('/' == second[0]) 
    586         { 
    587             second_slash: ; 
    588             return first ~ second; 
    589         } 
    590         else 
    591         { 
    592             version(Windows) 
    593             { 
    594                 if('\\' == second[0]) 
    595                     goto second_slash; 
    596             } 
    597              
    598             return first ~ std.path.sep ~ second; 
    599         } 
    600     } 
     503        return std.path.join(currentDir, p); 
     504    } 
     505
     506 
     507unittest 
     508
     509    string curdir = r"d:\foo"; 
     510    assert(getAbsolutePath(r"C:\Bar", curdir) == r"C:\Bar"); 
     511    assert(getAbsolutePath(r"", curdir) == r"d:\foo"); 
     512    assert(getAbsolutePath(r"bar", curdir) == r"d:\foo\bar"); 
     513    assert(getAbsolutePath(r"bar\file.x", curdir) == r"d:\foo\bar\file.x"); 
     514    assert(getAbsolutePath(r"\all\your", curdir) == r"d:\all\your"); 
     515    //assert(getAbsolutePath(r"C:Bar", curdir) == r"C:\foo\Bar"); // Alt. 
     516    assert(getAbsolutePath(r"C:Bar", curdir) == r"C:\Bar"); 
     517    assert(getAbsolutePath(r"D:Bar", curdir) == r"d:\foo\Bar"); 
    601518} 
    602519 
     
    773690} 
    774691 
     692 
     693// s is the string to get modified; rep are char pairs, a char is mapped to the next one. 
     694char[] replacechars(char[] s, char[] rep ...) 
     695in 
     696{ 
     697    assert(0 == (rep.length % 2)); 
     698} 
     699body 
     700{ 
     701    size_t irep; 
     702    size_t iw; 
     703    char[] result; 
     704    for(iw = 0; iw != s.length; iw++) 
     705    { 
     706        for(irep = 0; irep < rep.length; irep += 2) 
     707        { 
     708            if(s[iw] == rep[irep]) 
     709            { 
     710                result = s.dup; 
     711                goto do_rep; 
     712            } 
     713        } 
     714    } 
     715    return s; 
     716    for(; iw != s.length; iw++) 
     717    { 
     718        for(irep = 0; irep < rep.length; irep += 2) 
     719        { 
     720            if(s[iw] == rep[irep]) 
     721            { 
     722                do_rep: // Jump in with valid iw and irep. 
     723                result[iw] = rep[irep + 1]; 
     724                break; 
     725            } 
     726        } 
     727    } 
     728    return result; 
     729} 
     730 
     731unittest 
     732{ 
     733    assert("foobar" == replacechars("buuqar", 'u','o', 'q','b', 'b','f')); 
     734    assert("foobar" == replacechars("foobar")); 
     735    assert("foobar" == replacechars("foobar", 'x','y', 'a','a')); 
     736    assert("foobar" == replacechars("foobaz", 'x','y', 'z','r')); 
     737} 
     738 
     739 
     740bool startswith(char[] str, char[] swith) 
     741{ 
     742    return swith.length <= str.length && str[0 .. swith.length] == swith; 
     743} 
     744 
     745unittest 
     746{ 
     747    assert(startswith("foobar", "foo")); 
     748    assert(startswith("foobar", "f")); 
     749    assert(startswith("foobar", "foobar")); 
     750     
     751    assert(!startswith("foobar", "F")); 
     752    assert(!startswith("foobar", "Foobar")); 
     753    assert(!startswith("foobar", "oobar")); 
     754    assert(!startswith("foobar", "ffoobar")); 
     755    assert(!startswith("foobar", "foobare")); 
     756    assert(!startswith("foobar", "foobarr")); 
     757} 
     758 
     759 
     760dchar rawlower(dchar ch) 
     761{ 
     762    if(ch >= 'A' && ch <= 'Z') 
     763        return 'a' + (ch - 'A'); 
     764    return ch; 
     765} 
     766 
     767unittest 
     768{ 
     769    assert(rawlower('a') == 'a'); 
     770    assert(rawlower('A') == 'a'); 
     771    assert(rawlower('f') == 'f'); 
     772    assert(rawlower('F') == 'f'); 
     773    assert(rawlower('w') == 'w'); 
     774    assert(rawlower('W') == 'w'); 
     775    assert(rawlower('5') == '5'); 
     776    assert(rawlower('!') == '!'); 
     777    assert(rawlower(' ') == ' '); 
     778    assert(rawlower('\0') == '\0'); 
     779    assert(rawlower('\u00FC') == '\u00FC'); 
     780} 
     781 
     782 
     783int findraw(void[] str, void[] find) 
     784{ 
     785    if(!find.length) 
     786        return 0; 
     787    byte[] s = cast(byte[])str; 
     788    byte[] f = cast(byte[])find; 
     789    findloop: 
     790    for(; s.length >= f.length; s = s[1 .. $]) 
     791    { 
     792        if(s[0] == f[0]) 
     793        { 
     794            for(int i = 1; i < f.length; i++) 
     795            { 
     796                if(s[i] != f[i]) 
     797                    continue findloop; 
     798            } 
     799            return s.ptr - str.ptr; 
     800        } 
     801    } 
     802    return -1; 
     803} 
     804 
     805unittest 
     806{ 
     807    assert(findraw("foo", "bar") == -1); 
     808    assert(findraw("Foo", "BAR") == -1); 
     809    assert(findraw("foo", "O") == -1); 
     810    assert(findraw("foo", "oo") == 1); 
     811    assert(findraw("foo", "ou") == -1); 
     812    assert(findraw("foo", "ooo") == -1); 
     813} 
     814 
     815 
     816int ifindraw(void[] str, void[] find) 
     817{ 
     818    if(!find.length) 
     819        return 0; 
     820    ubyte[] s = cast(ubyte[])str; 
     821    ubyte[] f = cast(ubyte[])find; 
     822    findloop: 
     823    for(; s.length >= f.length; s = s[1 .. $]) 
     824    { 
     825        //printf("r = %x == %x    ", (s[0]), (f[0]) ); 
     826        //printf("i = %x == %x    ", (s[0] & ~32), (f[0] & ~32) ); 
     827        //printf("c = %c == %c  \n", (s[0]), (f[0]) ); 
     828        if( 
     829            ((s[0] & ~32) == (f[0] & ~32) 
     830                && (s[0] == f[0] 
     831                    || rawlower(s[0]) == rawlower(f[0]) 
     832                    ) 
     833                ) 
     834            ) 
     835        { 
     836            for(int i = 1; i < f.length; i++) 
     837            { 
     838                if(rawlower(s[i]) != rawlower(f[i])) 
     839                    continue findloop; 
     840            } 
     841            return s.ptr - str.ptr; 
     842        } 
     843    } 
     844    return -1; 
     845} 
     846 
     847unittest 
     848{ 
     849    assert(ifindraw("foo", "bar") == -1); 
     850    assert(ifindraw("Foo", "BAR") == -1); 
     851    assert(ifindraw("foo", "O") == 1); 
     852    assert(ifindraw("foo", "oo") == 1); 
     853    assert(ifindraw("foo", "OO") == 1); 
     854    assert(ifindraw("foo", "fOO") == 0); 
     855    assert(ifindraw("foo", "ou") == -1); 
     856    assert(ifindraw("foo", "ooo") == -1); 
     857    assert(ifindraw("foo", "fooo") == -1); 
     858} 
     859 
     860 
     861int findany(string s, string[] lookfor ...) 
     862{ 
     863    for(string ss = s; ss.length; ss = ss[1 .. $]) 
     864    { 
     865        for(int i = 0; i < lookfor.length; i++) 
     866        { 
     867            if(startswith(ss, lookfor[i])) 
     868            { 
     869                return ss.ptr - s.ptr; 
     870            } 
     871        } 
     872    } 
     873    return -1; 
     874} 
     875 
     876unittest 
     877{ 
     878    assert(findany("foobar", "foo") == 0); 
     879    assert(findany("foobar", "oo") == 1); 
     880    assert(findany("foobar", "b", "bar") == 3); 
     881    assert(findany("foobar", "b", "foo") == 0); 
     882    assert(findany("foobar", "foo", "b") == 0); 
     883    assert(findany("foobar", "x") == -1); 
     884    assert(findany("foobar", "x", "y", "x") == -1); 
     885    assert(findany("foobar", "x", "b") == 3); 
     886    assert(findany("foobar", "b", "b", "b", "b") == 3); 
     887} 
     888 
     889 
     890// s is the string to get modified; rep are string pairs, a string is mapped to the next one. 
     891char[] replacestrings(char[] s, char[][] rep ...) 
     892in 
     893{ 
     894    assert(0 == (rep.length % 2)); 
     895} 
     896body 
     897{ 
     898    char[] result; 
     899    size_t startiw, iw; 
     900    for(iw = startiw = 0;; iw++) 
     901    { 
     902        at_iw: ; 
     903        if(iw == s.length) 
     904            break; 
     905        for(size_t irep = 0; irep < rep.length; irep += 2) 
     906        { 
     907            if(0 == rep[irep].length) 
     908                continue; 
     909            if(startswith(s[iw .. $], rep[irep])) 
     910            { 
     911                if(iw) 
     912                    result ~= s[startiw .. iw]; 
     913                result ~= rep[irep + 1]; 
     914                iw += rep[irep].length; 
     915                startiw = iw; 
     916                goto at_iw; 
     917            } 
     918        } 
     919    } 
     920    if(0 == startiw) 
     921        return s; 
     922    if(startiw != iw) 
     923        result ~= s[startiw .. $]; 
     924    return result; 
     925} 
     926 
     927unittest 
     928{ 
     929    assert("foobar" == replacestrings("foou", "","X", "u","bar")); 
     930    assert("foobar" == replacestrings("foobar", "f","f")); 
     931    assert("foobar" == replacestrings("foobar")); 
     932    assert("foobar" == replacestrings("foobar")); 
     933    assert("foobar" == replacestrings("foobar", "r","r")); 
     934    assert("foobar" == replacestrings("FOOBAR", "FOOBAR","foobar")); 
     935    assert("foobar" == replacestrings("foobar", "bare","X")); 
     936    assert("foobar" == replacestrings("foobar", "F","X")); 
     937    assert("foobar" == replacestrings("buuqar", "u","o", "q","b", "b","f")); 
     938} 
     939 
     940 
     941int isEolChar(char ch) 
     942{ 
     943    return '\r' == ch || '\n' == ch; 
     944} 
     945 
     946 
     947/// Returns: the next word and updates line to exclude it. 
     948char[] nextWord(inout char[] line) 
     949{ 
     950    if(!line.length) 
     951        return null; 
     952     
     953    char[] result; 
     954    uint i; 
     955     
     956    for(i = 0; i != line.length; i++) 
     957    { 
     958        if(line[i] == ' ') 
     959        { 
     960            // Found a word. 
     961            result = line[0 .. i]; 
     962            line = line[i + 1 .. line.length]; 
     963            return result; 
     964        } 
     965    } 
     966     
     967    // Fell through, last word. 
     968    result = line; 
     969    line = null; 
     970    return result; 
     971} 
     972 
     973 
     974char* myStringz(char[] s) 
     975{ 
     976    if(!s.length) 
     977        return ""; 
     978     
     979    // Check if already null terminated. 
     980    if(!s.ptr[s.length]) // Disables bounds checking. 
     981        return s.ptr; 
     982     
     983    // Need to duplicate with null terminator. 
     984    char[] result; 
     985    result = new char[s.length + 1]; 
     986    result[s.length] = 0; 
     987    result = result[0 .. s.length]; 
     988    result[] = s; 
     989    return result.ptr; 
     990} 
     991 
     992 
     993// Makes path relative to the specialDir if possible. 
     994// This version expects path and specialDir to be clean (cleanPath) 
     995string getRelativePath_clean(string path, string specialDir) 
     996{ 
     997    int igooddir = 0; 
     998    int numparentdirs = 0; 
     999    for(int i = 0;; i++) 
     1000    { 
     1001        if(i == specialDir.length) 
     1002        { 
     1003            if(i == path.length) 
     1004                igooddir = i; 
     1005            else if('\\' == path[i]) 
     1006                igooddir = i + 1; 
     1007            break; 
     1008        } 
     1009        if(i == path.length) 
     1010            break; 
     1011        if(!fncharmatch(path[i], specialDir[i])) 
     1012        { 
     1013            if(igooddir) 
     1014                numparentdirs = 1; 
     1015            break; 
     1016        } 
     1017        // (i > 1) to exclude \\ from network path. 
     1018        if(i > 1 && '\\' == specialDir[i]) 
     1019        { 
     1020            igooddir = i + 1; 
     1021        } 
     1022    } 
     1023    if(igooddir) 
     1024    { 
     1025        // path[0 .. igooddir] are the common directories with specialDir 
     1026        for(int i = igooddir; i < specialDir.length; i++) 
     1027        { 
     1028            if('\\' == specialDir[i]) 
     1029                numparentdirs++; 
     1030        } 
     1031        if(numparentdirs) 
     1032        { 
     1033            char[] dots; 
     1034            for(int i = 0; i < numparentdirs; i++) 
     1035            { 
     1036                dots ~= r"..\"; 
     1037            } 
     1038            path = dots ~ path[igooddir .. $]; 
     1039        } 
     1040        else 
     1041        { 
     1042            path = path[igooddir .. $]; 
     1043        } 
     1044    } 
     1045    if(path.length == 2 && path[1] == ':') 
     1046        return path ~ "\\"; 
     1047    return path; 
     1048} 
     1049 
     1050// Makes path relative to the specialDir if possible. 
     1051string getRelativePath(string path, string specialDir) 
     1052{ 
     1053    return getRelativePath_clean(cleanPath(path), cleanPath(specialDir)); 
     1054} 
     1055 
     1056unittest 
     1057{ 
     1058    assert(getRelativePath(r"C:\foo\bar", r"c:\foo") == r"bar"); 
     1059    assert(getRelativePath(r"C:\baz", r"c:\") == r"baz"); 
     1060    assert(getRelativePath(r"C:\FOO\Cat", r"c:\foo\bar\baz") == r"..\..\Cat"); 
     1061    assert(getRelativePath(r"C:\FOO\Cat", r"d:\foo\bar\baz") == r"C:\FOO\Cat"); 
     1062    assert(getRelativePath(r"C:\baz\", r"c:\") == r"baz"); 
     1063    //mixin(assertexpr!(`getRelativePath(r"C:\", r"c:\baz\") == r"..\"`)); 
     1064    mixin(assertexpr!(`getRelativePath(r"C:\", r"c:") == r""`)); 
     1065} 
     1066 
     1067 
     1068// Removes extra slashes/backslashes, 
     1069// translates "." and "..". 
     1070string cleanPath(string path) 
     1071{ 
     1072    if(!path.length) 
     1073        return ""; 
     1074    // Handle first char separately so it 
     1075    // allows network paths with two backslashes. 
     1076    char[] result = (new char[path.length])[0 .. 1]; 
     1077    { 
     1078        char ch = path[0]; 
     1079        if(ch == '/') 
     1080            ch = '\\'; 
     1081        result[0] = ch; 
     1082    } 
     1083    char prevchar = 0; 
     1084    int numdirdots = 0; 
     1085    if(result[0] == '.') 
     1086        numdirdots++; 
     1087     
     1088    void handledots() 
     1089    { 
     1090        mixin(assertexpr!((`numdirdots > 0`)));; 
     1091        int origdots = numdirdots; 
     1092        void baddots() 
     1093        { 
     1094            char[] dotchars = new char[origdots]; 
     1095            dotchars[] = '.'; 
     1096            throw new Exception("Unable to resolve '" ~ dotchars ~ "' in '" ~ path ~ "'"); 
     1097        } 
     1098        for(numdirdots--;; numdirdots--) 
     1099        { 
     1100            prevchar = 0; 
     1101            for(;;) 
     1102            { 
     1103                if(!result.length) 
     1104                    break; 
     1105                if('\\' == result[$ - 1]) 
     1106                { 
     1107                    result = result[0 .. $ - 1]; 
     1108                    prevchar = '\\'; 
     1109                    break; 
     1110                } 
     1111                result = result[0 .. $ - 1]; 
     1112            } 
     1113            if(numdirdots == 0) 
     1114                break; 
     1115        } 
     1116        if('\\' == prevchar) 
     1117            result ~= '\\'; 
     1118        if((!result.length || r"\\" == result) && origdots > 1) // e.g. `.\` was fine 
     1119            baddots(); 
     1120    } 
     1121     
     1122    for(int i = 1;; i++) 
     1123    { 
     1124        char ch; 
     1125        if(i >= path.length) 
     1126        { 
     1127            if(numdirdots > 0) 
     1128                handledots(); 
     1129            break; 
     1130        } 
     1131        ch = path[i]; 
     1132        if(ch == '/') 
     1133            ch = '\\'; 
     1134        if('.' == ch 
     1135            && (numdirdots > 0 || '\\' == prevchar)) 
     1136        { 
     1137            numdirdots++; 
     1138        } 
     1139        if(ch == '\\') 
     1140        { 
     1141            if(numdirdots) 
     1142            { 
     1143                handledots(); 
     1144            } 
     1145            else 
     1146            { 
     1147                if(prevchar != '\\') 
     1148                    result ~= '\\'; 
     1149            } 
     1150        } 
     1151        else 
     1152        { 
     1153            if('.' != ch) 
     1154                numdirdots = 0; 
     1155            result ~= ch; 
     1156        } 
     1157        prevchar = ch; 
     1158    } 
     1159    // If trailing backslash, trim it off, as long as 
     1160    // it's not part of leading network path two backslashes. 
     1161    if(prevchar == '\\' && result.length > 2) 
     1162        result = result[0 .. $ - 1]; 
     1163    return result; 
     1164} 
     1165 
     1166template assertexpr(string EXPR, string TEXT = "") 
     1167{ 
     1168    debug 
     1169    { 
     1170        const string assertexpr = "if(!(" ~ EXPR ~ "))" 
     1171            ~ "{" 
     1172            ~   "scope _stdasserterror = new class { public import std.asserterror; };" 
     1173            ~   "throw new _stdasserterror.AssertError(__FILE__, __LINE__, `" ~ EXPR ~ "  " ~ TEXT ~ "`);" 
     1174            ~ "}"; 
     1175    } 
     1176    else 
     1177    { 
     1178        const string assertexpr = ""; 
     1179    } 
     1180} 
     1181 
     1182unittest 
     1183{ 
     1184    mixin(assertexpr!(`cleanPath(r"\\foo\bar") == r"\\foo\bar"`)); 
     1185    mixin(assertexpr!(`cleanPath(r"//foo/\bar") == r"\\foo\bar"`)); 
     1186    mixin(assertexpr!(`cleanPath(r"\\") == r"\\"`)); 
     1187     
     1188    mixin(assertexpr!(`cleanPath(r"c:\all\your\base") == r"c:\all\your\base"`)); 
     1189    mixin(assertexpr!(`cleanPath(r"c:\/\all/\/\\your//\\\\base") == r"c:\all\your\base"`)); 
     1190    mixin(assertexpr!(`cleanPath(r"c:\all\your\base\") == r"c:\all\your\base"`)); 
     1191    mixin(assertexpr!(`cleanPath(r"c:\all\your\base///\\") == r"c:\all\your\base"`)); 
     1192    mixin(assertexpr!(`cleanPath(r"c:\\\all\your\base") == r"c:\all\your\base"`)); 
     1193    mixin(assertexpr!(`cleanPath(r"c:\all\your\base\this.file") == r"c:\all\your\base\this.file"`)); 
     1194    mixin(assertexpr!(`cleanPath(r"c:\all your base\this.file") == r"c:\all your base\this.file"`)); 
     1195     
     1196    mixin(assertexpr!(`cleanPath(r".\foo\bar") == r"foo\bar"`)); 
     1197    //struct _83jh38h { import std.stdio; } 
     1198    //_83jh38h.writefln("unittest: %s", cleanPath(r"c:\foo\bar\.\baz\..\this.file")); 
     1199    mixin(assertexpr!(`cleanPath(r"c:\foo\bar\.\baz\..\this.file") == r"c:\foo\bar\this.file"`)); 
     1200    mixin(assertexpr!(`cleanPath(r"c:\foo\bar\.\baz\..\..\this.file") == r"c:\foo\this.file"`)); 
     1201    //mixin(assertexpr!(`cleanPath(r"c:\..\this.file") != r"this.file"`)); 
     1202    //mixin(assertexpr!(`cleanPath(r"c:\..\this.file") != r"\this.file"`)); 
     1203} 
     1204 
     1205 
     1206string[] parseArgs(string args) 
     1207{ 
     1208    string[] result; 
     1209    uint i; 
     1210    bool inQuote = false; 
     1211    bool findStart = true; 
     1212    uint startIndex = 0; 
     1213     
     1214    for(i = 0;; i++) 
     1215    { 
     1216        if(i == args.length) 
     1217        { 
     1218            if(findStart) 
     1219                startIndex = i; 
     1220            break; 
     1221        } 
     1222         
     1223        if(findStart) 
     1224        { 
     1225            if(args[i] == ' ' || args[i] == '\t') 
     1226                continue; 
     1227            findStart = false; 
     1228            startIndex = i; 
     1229        } 
     1230         
     1231        if(args[i] == '"') 
     1232        { 
     1233            inQuote = !inQuote; 
     1234            if(!inQuote) //matched quotes 
     1235            { 
     1236                result.length = result.length + 1; 
     1237                result[result.length - 1] = args[startIndex .. i]; 
     1238                findStart = true; 
     1239            } 
     1240            else //starting quote 
     1241            { 
     1242                if(startIndex != i) //must be a quote stuck to another word, separate them 
     1243                { 
     1244                    result.length = result.length + 1; 
     1245                    result[result.length - 1] = args[startIndex .. i]; 
     1246                    startIndex = i + 1; 
     1247                } 
     1248                else 
     1249                { 
     1250                    startIndex++; //exclude the quote 
     1251                } 
     1252            } 
     1253        } 
     1254        else if(!inQuote) 
     1255        { 
     1256            if(args[i] == ' ' || args[i] == '\t') 
     1257            { 
     1258                result.length = result.length + 1; 
     1259                result[result.length - 1] = args[startIndex .. i]; 
     1260                findStart = true; 
     1261            } 
     1262        } 
     1263    } 
     1264     
     1265    if(startIndex != i) 
     1266    { 
     1267        result.length = result.length + 1; 
     1268        result[result.length - 1] = args[startIndex .. i]; 
     1269    } 
     1270     
     1271    return result; 
     1272} 
     1273 
     1274unittest 
     1275{ 
     1276    string[] args; 
     1277     
     1278    args = parseArgs(`"foo" bar`); 
     1279    assert(args.length == 2); 
     1280    assert(args[0] == "foo"); 
     1281    assert(args[1] == "bar"); 
     1282     
     1283    args = parseArgs(`"environment"`); 
     1284    assert(args.length == 1); 
     1285    assert(args[0] == "environment"); 
     1286     
     1287    /+ 
     1288    writefln("commandLine = '%s'", Environment.commandLine); 
     1289    foreach(string arg; Environment.getCommandLineArgs()) 
     1290    { 
     1291        writefln("\t'%s'", arg); 
     1292    } 
     1293    +/ 
     1294} 
     1295 
     1296 
     1297/+ 
     1298abstract class MSlice(TElem) 
     1299{ 
     1300    TElem opIndex(size_t); 
     1301    MSlice opSlice(size_t, size_t); 
     1302    size_t length(); // getter 
     1303} 
     1304 
     1305 
     1306class MSliceArray(TElem): MSlice(TElem) 
     1307{ 
     1308    this(TElem[] array) 
     1309    { 
     1310        this.array = array; 
     1311    } 
     1312     
     1313     
     1314    override TElem opIndex(size_t idx) 
     1315    { 
     1316        return array[idx]; 
     1317    } 
     1318     
     1319     
     1320    override TElem opSlice(size_t idx1, size_t idx2) 
     1321    { 
     1322        return array[idx1 .. idx2]; 
     1323    } 
     1324     
     1325     
     1326    override size_t length() // getter 
     1327    { 
     1328        return array.length; 
     1329    } 
     1330     
     1331     
     1332    protected: 
     1333    TElem[] array; 
     1334} 
     1335+/ 
     1336 
  • trunk/win32/entice/winapi.d

    r101 r102  
    1 public import dfl.winapi; 
     1public import dfl.internal.winapi; 
    22 
    33 
     
    166166    enum: UINT 
    167167    { 
    168     DRIVE_FIXED = 3, 
    169     } 
    170  
    171  
    172     alias DWORD function(LPCWSTR lpszLongPath,LPWSTR lpszShortPath,DWORD cchBuffer) GetShortPathNameWProc; 
     168        DRIVE_FIXED = 3, 
     169    } 
    173170     
    174171     
     
    192189     
    193190    BOOL ReplyMessage(LRESULT lResult); 
     191     
     192     
     193    struct STARTUPINFO { 
     194      DWORD  cb; 
     195      LPTSTR lpReserved; 
     196      LPTSTR lpDesktop; 
     197      LPTSTR lpTitle; 
     198      DWORD  dwX; 
     199      DWORD  dwY; 
     200      DWORD  dwXSize; 
     201      DWORD  dwYSize; 
     202      DWORD  dwXCountChars; 
     203      DWORD  dwYCountChars; 
     204      DWORD  dwFillAttribute; 
     205      DWORD  dwFlags; 
     206      WORD   wShowWindow; 
     207      WORD   cbReserved2; 
     208      LPBYTE lpReserved2; 
     209      HANDLE hStdInput; 
     210      HANDLE hStdOutput; 
     211      HANDLE hStdError; 
     212    } 
     213     
     214    alias STARTUPINFO* LPSTARTUPINFO; 
     215     
     216     
     217    struct PROCESS_INFORMATION { 
     218      HANDLE hProcess; 
     219      HANDLE hThread; 
     220      DWORD  dwProcessId; 
     221      DWORD  dwThreadId; 
     222    } 
     223     
     224    alias PROCESS_INFORMATION* LPPROCESS_INFORMATION; 
     225     
     226     
     227    BOOL CreateProcessW( 
     228     LPCWSTR lpApplicationName, 
     229     LPWSTR lpCommandLine, 
     230     LPSECURITY_ATTRIBUTES lpProcessAttributes, 
     231     LPSECURITY_ATTRIBUTES lpThreadAttributes, 
     232     BOOL bInheritHandles, 
     233     DWORD dwCreationFlags, 
     234     LPVOID lpEnvironment, 
     235     LPWSTR lpCurrentDirectory, 
     236     LPSTARTUPINFO lpStartupInfo, 
     237     LPPROCESS_INFORMATION lpProcessInformation 
     238    ); 
     239     
     240    BOOL CreateProcessA( 
     241     LPCSTR lpApplicationName, 
     242     LPSTR lpCommandLine, 
     243     LPSECURITY_ATTRIBUTES lpProcessAttributes, 
     244     LPSECURITY_ATTRIBUTES lpThreadAttributes, 
     245     BOOL bInheritHandles, 
     246     DWORD dwCreationFlags, 
     247     LPVOID lpEnvironment, 
     248     LPTSTR lpCurrentDirectory, 
     249     LPSTARTUPINFO lpStartupInfo, 
     250     LPPROCESS_INFORMATION lpProcessInformation 
     251    ); 
     252 
     253     
    194254} 
    195255