Annotation of mstools/mfc/samples/restool/restool.cpp, revision 1.1.1.2

1.1       root        1: // restool.cpp : Parses RES files, making Foundation-ready header files for
                      2: //               all dialogs in it.  This can make it easier to port the
                      3: //               dialog code from existing applications, but it is not
                      4: //               intended to make writing new dialog code easier or better.
                      5: //
                      6: // This is a part of the Microsoft Foundation Classes C++ library.
                      7: // Copyright (C) 1992 Microsoft Corporation
                      8: // All rights reserved.
                      9: //
                     10: // This source code is only intended as a supplement to the
                     11: // Microsoft Foundation Classes Reference and Microsoft
                     12: // QuickHelp documentation provided with the library.
                     13: // See these sources for detailed information regarding the
                     14: // Microsoft Foundation Classes product.
                     15: 
                     16: #include <afx.h>
                     17: #include <afxcoll.h>
                     18: 
                     19: #include <windows.h>
                     20: 
                     21: #include <fcntl.h>
                     22: #include <io.h>
                     23: #include <ctype.h>
                     24: 
                     25: #include "dlgres.h"
                     26: 
                     27: /////////////////////////////////////////////////////////////////////////////
                     28: 
                     29: // forward declarations
                     30: BOOL GenDialog(const char*, const char*, int, long, BYTE*);
                     31: 
                     32: BOOL CheckResFile(int fh, long cbytes)
                     33: {
                     34:        long lFilesize, lCurloc;
                     35:        BYTE ch;
                     36:        int iType, inum, n;
                     37:        long l;
                     38:        BYTE* pBuffer;
                     39:        char szDlgName[128];
                     40:        char szResourceName[128];
                     41: 
                     42:        lFilesize = cbytes;
                     43:        lCurloc = 0;
                     44:        if (lCurloc == lFilesize)
                     45:                return FALSE;
                     46:        while (lCurloc < lFilesize)
                     47:        {
                     48:                n = _read(fh, &ch, 1);
                     49:                if (!CheckReadValue(n))
                     50:                        return FALSE;
                     51:                if (ch == 0xFF)
                     52:                {
                     53:                        n = _read(fh, &iType, 2);
                     54:                        if (!CheckReadValue(n))
                     55:                                return FALSE;
                     56:                }
                     57:                else
                     58:                {
                     59:                        while (ch != 0)
                     60:                        {
                     61:                                n = _read(fh, &ch, 1);
                     62:                                if (!CheckReadValue(n))
                     63:                                        return FALSE;
                     64:                        }
                     65:                }
                     66:                // read name of resource
                     67:                n = _read(fh, &ch, 1);
                     68:                if (!CheckReadValue(n))
                     69:                        return FALSE;
                     70: 
                     71:                if (ch == 0xFF)
                     72:                {
                     73:                        // numbered dialog template resource
                     74:                        n = _read(fh, &inum, 2);
                     75:                        if (!CheckReadValue(n))
                     76:                                return FALSE;
                     77:                        sprintf(szDlgName, "DLG%d", inum);
                     78:                        sprintf(szResourceName, "MAKEINTRESOURCE(%d)", inum);
                     79:                }
                     80:                else
                     81:                {
                     82:                        char* psz;
                     83:                        psz = szDlgName;
                     84:                        while (ch != 0)
                     85:                        {
                     86:                                *psz++ = ch;
                     87:                                n = _read(fh, &ch, 1);
                     88:                                if (!CheckReadValue(n))
                     89:                                        return FALSE;
                     90:                        }
                     91:                        *psz = 0;
                     92:                        sprintf(szResourceName, "\"%s\"", szDlgName);
                     93:                }
                     94:                n = _read(fh, &inum, 2);
                     95:                if (!CheckReadValue(n))
                     96:                        return FALSE;
                     97:                n = _read(fh, &l, sizeof(long));
                     98:                if (!CheckReadValue(n))
                     99:                        return FALSE;
                    100: 
                    101:                pBuffer = new BYTE[(size_t)l];
                    102:                if (!pBuffer)
                    103:                        return FALSE;
                    104: 
                    105:                n = _read(fh, pBuffer, (int)l);
                    106: 
                    107:                if (iType == 5)
                    108:                {
                    109:                        // Convert all but first letter of "class name" to lower case.
                    110:                        //
                    111:                        {
                    112:                                char* pch = szDlgName;
                    113:                                if (*pch)
                    114:                                {
                    115:                                        *pch = toupper(*pch);
                    116:                                        for (pch++; *pch; pch++)
                    117:                                                *pch = tolower(*pch);
                    118:                                }
                    119:                        }
                    120: 
                    121:                        if (!GenDialog(szDlgName, szResourceName, inum, l, pBuffer))
                    122:                                return FALSE;
                    123:                }
                    124: 
                    125:                delete pBuffer;
                    126: 
                    127:                if (n != l)
                    128:                        return FALSE;
                    129: 
                    130:                lCurloc = _lseek(fh, 0l, 1);
                    131:        }
                    132:        if (lCurloc != lFilesize)
                    133:                return FALSE;
                    134: 
                    135:        return TRUE;
                    136: }
                    137: 
                    138: int main(int argc, char* argv[])
                    139: {
                    140:        int fh;
                    141:        long lBytes;
                    142: 
                    143:        if (argc != 2)
                    144:        {
                    145:                fprintf(stderr, "restool : usage: restool file.res >file.h\n");
                    146:                fprintf(stderr, "           Parses RES files, making Foundation-ready H files for\n");
                    147:                fprintf(stderr, "           all dialogs in it.  This can make it easier to port the\n");
                    148:                fprintf(stderr, "           dialog code from existing applications.\n");
                    149:                fprintf(stderr, "           The output should be redirected into an H file for use.\n");
                    150:                exit(1);
                    151:        }
                    152: 
                    153:        fh = _open(argv[1], O_BINARY);
                    154:        if (fh == -1)
                    155:        {
                    156:                fprintf(stderr, "restool : Cannot open file %s for reading.\n", argv[1]);
                    157:                exit(1);
                    158:        }
                    159:        lBytes = _lseek(fh, 0l, 2);
                    160:        _lseek(fh, 0l, 0);
                    161: 
                    162:        printf("// restool has generated the following header code from %s\n\n", argv[1]);
                    163:        if (!CheckResFile(fh, lBytes))
                    164:        {
                    165:                fprintf(stderr, "restool : Cannot parse file %s; may be invalid.\n", argv[1]);
                    166:                exit(1);
                    167:        }
                    168:        printf("\n\n// END OF restool code\n");
                    169: 
                    170:        return 0;
                    171: }
                    172: 
                    173: /////////////////////////////////////////////////////////////////////////////
                    174: // Information for control types
                    175: 
                    176: struct ControlType
                    177: {
                    178:        BYTE        code;       // if 0 => end, if 0xFF => match any
                    179:        BYTE        style;      // lower 4 bits of style
                    180:                                                        //   0xFF => accept any style
                    181: 
                    182:        const char* pszClass;   // if NULL use previous
                    183:        const char* pszNoun;    // if NULL use previous
                    184:        int         nCount;     // significant only if pszNoun != NULL
                    185: };
                    186: 
                    187: ControlType types[] =
                    188: {
                    189:        { BUTTONCODE,   BS_AUTOCHECKBOX,    "CButton",  "Check" },
                    190:        { BUTTONCODE,   BS_CHECKBOX,        NULL,       NULL },
                    191:        { BUTTONCODE,   BS_3STATE,          NULL,       NULL },
                    192:        { BUTTONCODE,   BS_AUTO3STATE,      NULL,       NULL },
                    193:        { BUTTONCODE,   BS_AUTORADIOBUTTON, NULL,       "Option" },
                    194:        { BUTTONCODE,   BS_RADIOBUTTON,     NULL,       NULL },
                    195:        { BUTTONCODE,   BS_GROUPBOX,        NULL,       "Group" },
                    196:        { BUTTONCODE,   BS_PUSHBUTTON,      NULL,       "Button" },
                    197:        { BUTTONCODE,   BS_DEFPUSHBUTTON,   NULL,       NULL },
                    198:        { EDITCODE,     0xFF,               "CEdit",    "Edit" },
                    199:        { STATICCODE,   SS_SIMPLE,          "CStatic",  "Text" },
                    200:        { STATICCODE,   SS_LEFT,            NULL,       NULL },
                    201:        { STATICCODE,   SS_CENTER,          NULL,       NULL },
                    202:        { STATICCODE,   SS_RIGHT,           NULL,       NULL },
                    203:        { STATICCODE,   SS_LEFTNOWORDWRAP,  NULL,       NULL },
                    204:        { STATICCODE,   SS_ICON,            NULL,       "Icon" },
                    205:        { STATICCODE,   SS_BLACKRECT,       NULL,       "Box" },
                    206:        { STATICCODE,   SS_GRAYRECT,        NULL,       NULL },
                    207:        { STATICCODE,   SS_WHITERECT,       NULL,       NULL },
                    208:        { STATICCODE,   SS_BLACKFRAME,      NULL,       NULL },
                    209:        { STATICCODE,   SS_GRAYFRAME,       NULL,       NULL },
                    210:        { STATICCODE,   SS_WHITEFRAME,      NULL,       NULL },
                    211:        { LISTBOXCODE,  0xFF,               "CListBox", "List" },
                    212:        { COMBOBOXCODE, 0xFF,               "CComboBox", "Combo" },
                    213:        { SCROLLBARCODE, 0,                 "CScrollBar", "HScroll" },
                    214:        { SCROLLBARCODE, SBS_VERT,          NULL,       "VScroll" },
                    215:        { 0xFF,         0xFF,               "CWnd",     "Control" },    // 2nd last
                    216:        { 0 }
                    217: };
                    218: 
                    219: void InitCounts()
                    220: {
                    221:        for (register ControlType* pType = types; pType->code != 0; pType++)
                    222:                if (pType->pszNoun != NULL)
                    223:                        pType->nCount = 0;
                    224: }
                    225: 
                    226: // IsLabel:
                    227: // Simple logic for determining if an item is really a label.
                    228: // Labels do not (usually) need any code, so none is generated.
                    229: //
                    230: BOOL IsLabel(BYTE code, DLGITEMTEMPLATE* pDit, BYTE nextCode)
                    231: {
                    232:        if (pDit->id == -1)
                    233:                return TRUE;            // may not be real label, but ignore anyway
                    234: 
                    235:        if (code == STATICCODE && nextCode != 0)
                    236:        {
                    237:                // static code with something after it
                    238:                if (pDit->style & SS_NOPREFIX)
                    239:                        return FALSE;   // no accelerator => probably not a label
                    240: 
                    241:                switch (pDit->style & 0xf)
                    242:                {
                    243:                case SS_LEFT: case SS_CENTER: case SS_RIGHT:
                    244:                case SS_SIMPLE: case SS_LEFTNOWORDWRAP:
                    245:                        break;      // keep going
                    246:                default:
                    247:                        return FALSE;
                    248:                }
                    249: 
                    250:                // lastly, only keep labels if next item is edit or list/combo
                    251:                switch (nextCode)
                    252:                {
                    253:                case EDITCODE: case LISTBOXCODE: case COMBOBOXCODE:
                    254:                        return TRUE;
                    255:                }
                    256:        }
                    257:        return FALSE;
                    258: }
                    259: 
                    260: /////////////////////////////////////////////////////////////////////////////
                    261: 
                    262: // ControlInfo:
                    263: // Decode control information and place in easy-to-use structure.
                    264: //
                    265: struct ControlInfo
                    266: {
                    267:        BYTE code;
                    268:        BYTE style;     // lower 4 bits of style
                    269: 
                    270:        const char* pszClass;
                    271:        CString memberName;         // will be literal text for a label
                    272:        UINT id;
                    273: 
                    274:        // special values
                    275:        BOOL bLabel;                // label not an interactive control
                    276:        int nRadioGroup;            // or -1 for none
                    277: 
                    278:        ControlInfo()   // structure initialization
                    279:        {
                    280:                pszClass = NULL;
                    281:                id = 0;
                    282:                bLabel = FALSE;
                    283:                nRadioGroup = -1;
                    284:        }
                    285: };
                    286: 
                    287: struct ControlInfo* DecodeControls(BYTE* pBuffer, BYTE* pEnd, int nCount)
                    288: {
                    289:        // decode controls in dialog
                    290:        CMapStringToPtr usedNames;
                    291:        CString lastLabel, lastLabelLiteral;
                    292:        lastLabel.GetBuffer(128);       // set a reasonable size
                    293:        lastLabelLiteral.GetBuffer(128);    // set a reasonable size
                    294: 
                    295:        struct ControlInfo* pAllInfo = new ControlInfo[nCount];
                    296:        ASSERT(pAllInfo != NULL);
                    297: 
                    298:        for (int iCtl = 0; iCtl < nCount; iCtl++)
                    299:        {
                    300:                struct ControlInfo* pInfo = &pAllInfo[iCtl];
                    301:                DLGITEMTEMPLATE* pDit = (DLGITEMTEMPLATE*)pBuffer;
                    302:                pBuffer += sizeof(DLGITEMTEMPLATE);
                    303: 
                    304:                BYTE cTokenCode = *pBuffer++;
                    305:                char* pszString = (char*)pBuffer;
                    306:                pBuffer = SkipString(pBuffer) + 1;
                    307: 
                    308:                ASSERT(pBuffer <= pEnd);
                    309:                pInfo->code = cTokenCode;
                    310:                pInfo->id = pDit->id;
                    311:                pInfo->style = (BYTE)(pDit->style&0xf);     // lower 4 bits of style
                    312: 
                    313:                if (*pszString != '\0')
                    314:                {
                    315:                        // save it away as a reasonable symbol
                    316:                        lastLabelLiteral = pszString;       // literal string (for comments)
                    317:                        lastLabel = "";
                    318: 
                    319:                        while (*pszString != '\0' && !isalpha(*pszString))
                    320:                                pszString++;        // skip non-alpha
                    321: 
                    322:                        // include alpha+numbers for the rest of the name
                    323:                        while (*pszString != '\0')
                    324:                        {
                    325:                                if (isalnum(*pszString))
                    326:                                        lastLabel += *pszString;
                    327:                                *pszString++;
                    328:                        }
                    329:                }
                    330: 
                    331:                BYTE nextCode = 0;
                    332:                if (pBuffer + sizeof(DLGITEMTEMPLATE) < pEnd)
                    333:                        nextCode = *(pBuffer+sizeof(DLGITEMTEMPLATE));
                    334: 
                    335:                if (IsLabel(cTokenCode, pDit, nextCode))
                    336:                {
                    337:                        pInfo->bLabel = TRUE;
                    338:                        pInfo->pszClass = NULL;
                    339:                        pInfo->memberName = lastLabelLiteral;
                    340:                        continue;
                    341:                }
                    342: 
                    343:                const char* pszClass = NULL;
                    344:                const char* pszNoun = NULL;
                    345:                BOOL bExact = FALSE;
                    346:                int* pnIndex = NULL;
                    347:                for (register ControlType* pType = types; pType->code != 0; pType++)
                    348:                {
                    349:                        if (pType->code == cTokenCode || pType->code == 0xFF)
                    350:                        {
                    351:                                // match raw category
                    352:                                if (pType->pszClass != NULL)
                    353:                                        pszClass = pType->pszClass;
                    354:                                ASSERT(pszClass != NULL);
                    355:                                if (pType->pszNoun != NULL)
                    356:                                {
                    357:                                        pszNoun = pType->pszNoun;
                    358:                                        pnIndex = &pType->nCount;
                    359:                                }
                    360: 
                    361:                                // check for sub-type match
                    362:                                if (pType->style == 0xFF ||
                    363:                                        ((BYTE)pType->style == (BYTE)(pDit->style&0xf)))
                    364:                                {
                    365:                                        // exact match
                    366:                                        bExact = TRUE;
                    367:                                        break;
                    368:                                }
                    369:                        }
                    370:                }
                    371: 
                    372:                ASSERT(bExact);
                    373:                (*pnIndex)++;       // bump count of objects using that noun
                    374: 
                    375:                // save remaining info
                    376:                pInfo->pszClass = pszClass;
                    377:                CString memberName;
                    378:                if (!lastLabel.IsEmpty())
                    379:                {
                    380:                        pInfo->memberName = lastLabel;
                    381:                        pInfo->memberName += pszNoun;
                    382:                }
                    383:                else
                    384:                {
                    385:                        pInfo->memberName = pszNoun;
                    386:                        char szT[10];
                    387:                        pInfo->memberName += _itoa(*pnIndex, szT, 10);
                    388:                }
                    389: 
                    390:                void* p;
                    391:                if (usedNames.Lookup(pInfo->memberName, p))
                    392:                {
                    393:                        // name has already been used in this class
                    394:                        char szT[10];
                    395:                        pInfo->memberName += _itoa(*pnIndex, szT, 10);
                    396:                }
                    397:                usedNames[pInfo->memberName] = "USED";
                    398: 
                    399:                lastLabel = "";
                    400:                lastLabelLiteral = "";
                    401:        }
                    402:        ASSERT(pBuffer == pEnd);
                    403:        return pAllInfo;        // return array
                    404: }
                    405: 
                    406: /////////////////////////////////////////////////////////////////////////////
                    407: // Print out control info
                    408: 
                    409: void PrintControls(const struct ControlInfo * pInfo, int nCount,
                    410:                DWORD /* styleDlg */)
                    411: {
                    412:        for (int iCtl = 0; iCtl < nCount; iCtl++, pInfo++)
                    413:        {
                    414:                if (pInfo->bLabel)
                    415:                {
                    416:                        printf("\t// label '%s'\n", (const char*)pInfo->memberName);
                    417:                }
                    418:                else
                    419:                {
                    420:                        // Build normal member type.
                    421:                        //
                    422:                        CString typeName = pInfo->pszClass;
                    423:                        typeName += '&';            // return reference
                    424:                        if (typeName.GetLength() < 8)
                    425:                                typeName += '\t';
                    426: 
                    427:                        // Write out member function definition.
                    428:                        printf("\t%s %s()\n"
                    429:                                "\t\t\t{ return *((%s*) GetDlgItem(%d)); } \n",
                    430:                                        (const char*)typeName,
                    431:                                        (const char*)pInfo->memberName,
                    432:                                        pInfo->pszClass, pInfo->id);
                    433:                }
                    434:        }
                    435: }
                    436: 
                    437: /////////////////////////////////////////////////////////////////////////////
                    438: 
                    439: // DetectRadioGroups:
                    440: // Special detection for radio groups.
                    441: //
                    442: void DetectRadioGroups(struct ControlInfo* pInfo, int nCount)
                    443: {
                    444:        int nRadioGroup = -1;
                    445:        UINT idLast = 0;
                    446: 
                    447:        for (int iCtl = 0; iCtl < nCount; iCtl++, pInfo++)
                    448:        {
                    449:                if (pInfo->code == BUTTONCODE &&
                    450:                        (pInfo->style == BS_AUTORADIOBUTTON ||
                    451:                         pInfo->style == BS_RADIOBUTTON))
                    452:                {
                    453:                        if (pInfo->id != idLast+1)
                    454:                        {
                    455:                                // start new group
                    456:                                nRadioGroup = -1;
                    457:                        }
                    458:                        pInfo->nRadioGroup = ++nRadioGroup;
                    459:                                // next in sequence
                    460:                }
                    461:                else
                    462:                {
                    463:                        nRadioGroup = -1;
                    464:                }
                    465:                idLast = pInfo->id;
                    466:        }
                    467: }
                    468: 
                    469: 
                    470: /////////////////////////////////////////////////////////////////////////////
                    471: 
                    472: // GenDialog:
                    473: // Do the actual code-generation work.
                    474: //
                    475: BOOL GenDialog(const char* pszName, const char* pszResourceName,
                    476:        int /* flags */, long l, BYTE* pBuffer)
                    477: {
                    478:        BYTE* pEnd = &pBuffer[l];
                    479: 
                    480:        InitCounts();
                    481: 
                    482:        DLGTEMPLATE* pdt = (DLGTEMPLATE*)pBuffer;
                    483:        pBuffer += sizeof(DLGTEMPLATE);
                    484:        DWORD styleDlg = pdt->style;
1.1.1.2 ! root      485:        int cdit = pdt->cdit;
1.1       root      486: 
                    487:        fprintf(stderr, "restool : Generating header for dialog %s.\n", pszName);
                    488: 
                    489:        // Make sure there is no menu string...
                    490:        if (*pBuffer != '\0')
                    491:                fprintf(stderr, "\nrestool : WARNING: Menus in dialogs are not supported.\n");
                    492:        pBuffer = SkipString(pBuffer);
                    493: 
                    494:        // Make sure only generic window class used
                    495: 
                    496:        if (*pBuffer != '\0')
                    497:                fprintf(stderr, "\nrestool : WARNING: Only generic window classes are supported.\n");
                    498:        pBuffer = SkipString(pBuffer);
                    499: 
                    500:        // Deal with caption string...
                    501:        char* pszCaption = (char*) pBuffer;
                    502:        pBuffer = SkipString(pBuffer);
                    503: 
                    504:        // Skip over font data if present
                    505:        if (styleDlg & DS_SETFONT)
                    506:                pBuffer = SkipString(pBuffer + sizeof(short int));
                    507: 
                    508:        // preliminary stuff
                    509:        const char* pszBaseClass;
                    510: 
                    511:        BOOL bModal = ((styleDlg & (DS_SYSMODAL | DS_MODALFRAME)) != 0);
                    512:        pszBaseClass = bModal ? "CModalDialog" : "CDialog";
                    513: 
                    514:        printf("///////////////////////////////////////////////////////////\n");
                    515:        printf("// class C%s manages the %s dialog resource\n\n", pszName,
                    516:                pszResourceName);
                    517:        printf("class C%s : public %s\n", pszName, pszBaseClass);
                    518:        printf("{\n");
                    519:        printf("public:\n");
                    520: 
                    521:        // Write the constructor.
                    522:        //
                    523:        printf("\tC%s(CWnd* pParentWnd = NULL)\n", pszName);
                    524:        if (bModal)
                    525:        {
                    526:                // CModalDialog constructor
                    527:                printf("\t\t: %s(%s, pParentWnd)\n", pszBaseClass, pszResourceName);
                    528:                printf("\t\t\t{ }\n");
                    529:        }
                    530:        else
                    531:        {
                    532:                // CModal dialog constructor + create modeless
                    533:                printf("\t\t{\n");
                    534:                printf("\t\t\tVERIFY(Create(%s, pParentWnd));\n", pszResourceName);
                    535:                printf("\t\t}\n");
                    536:        }
                    537: 
                    538:        // Write the public member variable declarations.
                    539:        //
                    540:        printf("\n\t// Attributes\n");
                    541:        struct ControlInfo* pAllInfo;
                    542:        pAllInfo = DecodeControls(pBuffer, pEnd, cdit);
                    543:        DetectRadioGroups(pAllInfo, cdit);
                    544:        PrintControls(pAllInfo, cdit, styleDlg);
                    545: 
                    546:        // Write the member function declarations.
                    547:        printf("\n\t// Operations\n");
                    548: 
                    549:        // Write the overriding virtual member function declarations.
                    550:        //
                    551:        printf("\n\t// Overridables\n");
                    552: 
                    553:        // Write the message-map and message-handling member function declarations.
                    554:        //
                    555:        printf("\n\t// Implementation\n");
                    556:        printf("private:\n");
                    557:        printf("\tBOOL OnInitDialog();\n");
                    558:        printf("\tDECLARE_MESSAGE_MAP()\n");
                    559:        printf("};\n\n");
                    560:        return TRUE;
                    561: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.