/** * Expected: * <pre> * "<whitespace> = <whitespace> [|"]<string>[|"]" * </pre> */ static boolean parseString(char** str, char* buf, size_t bufLen) { size_t len; char* end; if(!buf || bufLen == 0) return false; *str = M_SkipWhite(*str); if(**str != '=') return false; // Now I'm confused! // Skip over any leading whitespace. *str = M_SkipWhite(*str + 1); // Skip over any opening '"' character. if(**str == '"') (*str)++; // Find the end of the string. end = *str; while(*end && *end != '}' && *end != ',' && *end !='"') { end++; } len = end - *str; if(len != 0) { dd_snprintf(buf, MIN_OF(len+1, bufLen), "%s", *str); *str = end; } // Skip over any closing '"' character. if(**str == '"') (*str)++; return true; }
/** * Expected: * <pre> * "<whitespace> = <whitespace> <float>" * </pre> */ static float parseFloat(char** str) { float value; char* end; *str = M_SkipWhite(*str); if(**str != '=') return 0; // Now I'm confused! *str = M_SkipWhite(*str + 1); value = (float) strtod(*str, &end); *str = end; return value; }
static void drawEnteringTitle(void) { int x = SCREENWIDTH/2, y = WI_TITLEY; char* mapName = NULL; uint mapNum; ddmapinfo_t minfo; patchid_t patchId; patchinfo_t info; AutoStr* mapPath; Uri* mapUri; /// @kludge We need to properly externalize the map progression. if((gameModeBits & (GM_DOOM2|GM_DOOM2_PLUT|GM_DOOM2_TNT)) && wbs->nextMap == 30) { return; } /// kludge end. // See if there is a map name. mapUri = G_ComposeMapUri(wbs->episode, wbs->nextMap); mapPath = Uri_Compose(mapUri); if(Def_Get(DD_DEF_MAP_INFO, Str_Text(mapPath), &minfo) && minfo.name) { if(Def_Get(DD_DEF_TEXT, minfo.name, &mapName) == -1) mapName = minfo.name; } Uri_Delete(mapUri); // Skip the E#M# or Map #. if(mapName) { char* ptr = strchr(mapName, ':'); if(ptr) { mapName = M_SkipWhite(ptr + 1); } } DGL_Enable(DGL_TEXTURE_2D); DGL_Color4f(1, 1, 1, 1); FR_SetFont(FID(GF_FONTB)); FR_LoadDefaultAttrib(); FR_SetColorAndAlpha(defFontRGB2[CR], defFontRGB2[CG], defFontRGB2[CB], 1); // Draw "Entering" WI_DrawPatchXY3(pEntering, Hu_ChoosePatchReplacement(cfg.inludePatchReplaceMode, pEntering), x, y, ALIGN_TOP, 0, DTF_NO_TYPEIN); if(R_GetPatchInfo(pMapNames[wbs->nextMap], &info)) y += (5 * info.geometry.size.height) / 4; // Draw map. mapNum = (wbs->episode * 9) + wbs->nextMap; patchId = (mapNum < pMapNamesSize? pMapNames[mapNum] : 0); FR_SetColorAndAlpha(defFontRGB[CR], defFontRGB[CG], defFontRGB[CB], 1); WI_DrawPatchXY3(patchId, Hu_ChoosePatchReplacement2(cfg.inludePatchReplaceMode, patchId, mapName), x, y, ALIGN_TOP, 0, DTF_NO_TYPEIN); DGL_Disable(DGL_TEXTURE_2D); }
static void drawFinishedTitle(void) { int x = SCREENWIDTH/2, y = WI_TITLEY; patchid_t patchId; patchinfo_t info; char *mapName; uint mapNum; if(gameModeBits & (GM_ANY_DOOM2|GM_DOOM_CHEX)) mapNum = wbs->currentMap; else mapNum = (wbs->episode * 9) + wbs->currentMap; mapName = (char *) DD_GetVariable(DD_MAP_NAME); // Skip the E#M# or Map #. if(mapName) { char* ptr = strchr(mapName, ':'); if(ptr) { mapName = M_SkipWhite(ptr + 1); } } DGL_Enable(DGL_TEXTURE_2D); DGL_Color4f(1, 1, 1, 1); FR_SetFont(FID(GF_FONTB)); FR_LoadDefaultAttrib(); FR_SetColorAndAlpha(defFontRGB[CR], defFontRGB[CG], defFontRGB[CB], 1); // Draw <MapName> patchId = (mapNum < pMapNamesSize? pMapNames[mapNum] : 0); WI_DrawPatchXY3(patchId, Hu_ChoosePatchReplacement2(cfg.inludePatchReplaceMode, patchId, mapName), x, y, ALIGN_TOP, 0, DTF_NO_TYPEIN); if(R_GetPatchInfo(patchId, &info)) y += (5 * info.geometry.size.height) / 4; // Draw "Finished!" FR_SetColorAndAlpha(defFontRGB2[CR], defFontRGB2[CG], defFontRGB2[CB], 1); WI_DrawPatchXY3(pFinished, Hu_ChoosePatchReplacement(cfg.inludePatchReplaceMode, pFinished), x, y, ALIGN_TOP, 0, DTF_NO_TYPEIN); DGL_Disable(DGL_TEXTURE_2D); }
static void parseParamaterBlock(char** strPtr, drawtextstate_t* state, int* numBreaks) { (*strPtr)++; while(*(*strPtr) && *(*strPtr) != '}') { (*strPtr) = M_SkipWhite((*strPtr)); // What do we have here? if(!strnicmp((*strPtr), "flash", 5)) { (*strPtr) += 5; state->typeIn = true; } else if(!strnicmp((*strPtr), "noflash", 7)) { (*strPtr) += 7; state->typeIn = false; } else if(!strnicmp((*strPtr), "case", 4)) { (*strPtr) += 4; state->caseScale = true; } else if(!strnicmp((*strPtr), "nocase", 6)) { (*strPtr) += 6; state->caseScale = false; } else if(!strnicmp((*strPtr), "ups", 3)) { (*strPtr) += 3; state->caseMod[1].scale = parseFloat(&(*strPtr)); } else if(!strnicmp((*strPtr), "upo", 3)) { (*strPtr) += 3; state->caseMod[1].offset = parseFloat(&(*strPtr)); } else if(!strnicmp((*strPtr), "los", 3)) { (*strPtr) += 3; state->caseMod[0].scale = parseFloat(&(*strPtr)); } else if(!strnicmp((*strPtr), "loo", 3)) { (*strPtr) += 3; state->caseMod[0].offset = parseFloat(&(*strPtr)); } else if(!strnicmp((*strPtr), "break", 5)) { (*strPtr) += 5; ++(*numBreaks); } else if(!strnicmp((*strPtr), "r", 1)) { (*strPtr)++; state->rgba[CR] = parseFloat(&(*strPtr)); } else if(!strnicmp((*strPtr), "g", 1)) { (*strPtr)++; state->rgba[CG] = parseFloat(&(*strPtr)); } else if(!strnicmp((*strPtr), "b", 1)) { (*strPtr)++; state->rgba[CB] = parseFloat(&(*strPtr)); } else if(!strnicmp((*strPtr), "a", 1)) { (*strPtr)++; state->rgba[CA] = parseFloat(&(*strPtr)); } else if(!strnicmp((*strPtr), "x", 1)) { (*strPtr)++; state->offX = parseFloat(&(*strPtr)); } else if(!strnicmp((*strPtr), "y", 1)) { (*strPtr)++; state->offY = parseFloat(&(*strPtr)); } else if(!strnicmp((*strPtr), "scalex", 6)) { (*strPtr) += 6; state->scaleX = parseFloat(&(*strPtr)); } else if(!strnicmp((*strPtr), "scaley", 6)) { (*strPtr) += 6; state->scaleY = parseFloat(&(*strPtr)); } else if(!strnicmp((*strPtr), "scale", 5)) { (*strPtr) += 5; state->scaleX = state->scaleY = parseFloat(&(*strPtr)); } else if(!strnicmp((*strPtr), "angle", 5)) { (*strPtr) += 5; state->angle = parseFloat(&(*strPtr)); } else if(!strnicmp((*strPtr), "glitter", 7)) { (*strPtr) += 7; state->glitterStrength = parseFloat(&(*strPtr)); } else if(!strnicmp((*strPtr), "shadow", 6)) { (*strPtr) += 6; state->shadowStrength = parseFloat(&(*strPtr)); } else if(!strnicmp((*strPtr), "tracking", 8)) { (*strPtr) += 8; state->tracking = parseFloat(&(*strPtr)); } else { // Perhaps a font name? fontid_t fontId; if(!strnicmp((*strPtr), "font", 4)) { char buf[80]; (*strPtr) += 4; if(parseString(&(*strPtr), buf, 80)) { Uri* uri = Uri_NewWithPath2(buf, RC_NULL); fontId = Fonts_ResolveUri2(uri, true/*quiet please*/); Uri_Delete(uri); if(fontId != NOFONTID) { state->fontNum = fontId; continue; } } Con_Message("Warning:parseParamaterBlock: Unknown font '%s'.", (*strPtr)); continue; } // Unknown, skip it. if(*(*strPtr) != '}') (*strPtr)++; } } // Skip over the closing brace. if(*(*strPtr)) (*strPtr)++; }
/* * Draw a string of text controlled by parameter blocks. */ void WI_DrawParamText(int x, int y, char *string, dpatch_t * defFont, float defRed, float defGreen, float defBlue, boolean defCase, boolean defTypeIn) { char temp[256], *end; dpatch_t *font = defFont; float r = defRed, g = defGreen, b = defBlue; float offX = 0, offY = 0; float scaleX = 1, scaleY = 1, angle = 0, extraScale; float cx = x, cy = y; int charCount = 0; boolean typeIn = defTypeIn; boolean caseScale = defCase; struct { float scale, offset; } caseMod[2]; // 1=upper, 0=lower int curCase; caseMod[0].scale = 1; caseMod[0].offset = 3; caseMod[1].scale = 1.25f; caseMod[1].offset = 0; while(*string) { // Parse and draw the replacement string. if(*string == '{') // Parameters included? { string++; while(*string && *string != '}') { string = M_SkipWhite(string); // What do we have here? if(!strnicmp(string, "fonta", 5)) { font = hu_font_a; string += 5; } else if(!strnicmp(string, "fontb", 5)) { font = hu_font_b; string += 5; } else if(!strnicmp(string, "flash", 5)) { string += 5; typeIn = true; } else if(!strnicmp(string, "noflash", 7)) { string += 7; typeIn = false; } else if(!strnicmp(string, "case", 4)) { string += 4; caseScale = true; } else if(!strnicmp(string, "nocase", 6)) { string += 6; caseScale = false; } else if(!strnicmp(string, "ups", 3)) { string += 3; caseMod[1].scale = WI_ParseFloat(&string); } else if(!strnicmp(string, "upo", 3)) { string += 3; caseMod[1].offset = WI_ParseFloat(&string); } else if(!strnicmp(string, "los", 3)) { string += 3; caseMod[0].scale = WI_ParseFloat(&string); } else if(!strnicmp(string, "loo", 3)) { string += 3; caseMod[0].offset = WI_ParseFloat(&string); } else if(!strnicmp(string, "break", 5)) { string += 5; cx = x; cy += scaleY * SHORT(font[0].height); } else if(!strnicmp(string, "r", 1)) { string++; r = WI_ParseFloat(&string); } else if(!strnicmp(string, "g", 1)) { string++; g = WI_ParseFloat(&string); } else if(!strnicmp(string, "b", 1)) { string++; b = WI_ParseFloat(&string); } else if(!strnicmp(string, "x", 1)) { string++; offX = WI_ParseFloat(&string); } else if(!strnicmp(string, "y", 1)) { string++; offY = WI_ParseFloat(&string); } else if(!strnicmp(string, "scalex", 6)) { string += 6; scaleX = WI_ParseFloat(&string); } else if(!strnicmp(string, "scaley", 6)) { string += 6; scaleY = WI_ParseFloat(&string); } else if(!strnicmp(string, "scale", 5)) { string += 5; scaleX = scaleY = WI_ParseFloat(&string); } else if(!strnicmp(string, "angle", 5)) { string += 5; angle = WI_ParseFloat(&string); } else { // Unknown, skip it. if(*string != '}') string++; } } // Skip over the closing brace. if(*string) string++; } for(end = string; *end && *end != '{';) { if(caseScale) { curCase = -1; // Select a substring with characters of the same case // (or whitespace). for(; *end && *end != '{'; end++) { // We can skip whitespace. if(isspace(*end)) continue; if(curCase < 0) curCase = (isupper(*end) != 0); else if(curCase != (isupper(*end) != 0)) break; } } else { // Find the end of the visible part of the string. for(; *end && *end != '{'; end++); } strncpy(temp, string, end - string); temp[end - string] = 0; string = end; // Continue from here. // Setup the scaling. gl.MatrixMode(DGL_MODELVIEW); gl.PushMatrix(); // Rotate. if(angle != 0) { // The origin is the specified (x,y) for the patch. // We'll undo the VGA aspect ratio (otherwise the result would // be skewed). gl.Translatef(x, y, 0); gl.Scalef(1, 200.0f / 240.0f, 1); gl.Rotatef(angle, 0, 0, 1); gl.Scalef(1, 240.0f / 200.0f, 1); gl.Translatef(-x, -y, 0); } gl.Translatef(cx + offX, cy + offY + (caseScale ? caseMod[curCase].offset : 0), 0); extraScale = (caseScale ? caseMod[curCase].scale : 1); gl.Scalef(scaleX, scaleY * extraScale, 1); // Draw it. M_WriteText3(0, 0, temp, font, r, g, b, typeIn, typeIn ? charCount : 0); charCount += strlen(temp); // Advance the current position. cx += scaleX * M_StringWidth(temp, font); gl.MatrixMode(DGL_MODELVIEW); gl.PopMatrix(); } } }
//========================================================================== // ArgParse // Parses the given command line. //========================================================================== int ArgParse(int mode, const char *cmdline) { char word[512], *ptr, *response, *cmd = (char *) cmdline; int i; int count = 0; FILE *file; boolean quote = false; boolean is_response; // Init normal mode? if(mode == PM_NORMAL) arg_pos = 0; for(; *cmd;) { // Must allow: -cmd "echo ""this is a command""" // But also: @"\Program Files\test.rsp\" // And also: @\"Program Files"\test.rsp // Hello" My"Friend means "Hello MyFriend" // Skip initial whitespace. cmd = M_SkipWhite(cmd); // Check for response files. if(*cmd == '@') { is_response = true; cmd = M_SkipWhite(cmd + 1); } else { is_response = false; } for(ptr = word; *cmd && (quote || !isspace(*cmd)); cmd++) { if(!quote) { // We're not inside quotes. if(*cmd == '\"') // Quote begins. { quote = true; continue; } } else { // We're inside quotes. if(*cmd == '\"') // Quote ends. { if(cmd[1] == '\"') // Doubles? { // Normal processing, but output only one quote. cmd++; } else { quote = false; continue; } } } *ptr++ = *cmd; } // Append NULL to the word. *ptr++ = 0; // Word has been extracted, examine it. if(is_response) // Response file? { // Try to open it. if((file = fopen(word, "rt")) != NULL) { // How long is it? fseek(file, 0, SEEK_END); i = ftell(file); rewind(file); response = calloc(i + 1, 1); fread(response, 1, i, file); fclose(file); count += ArgParse(mode == PM_COUNT ? PM_COUNT : PM_NORMAL_REC, response); free(response); } } else if(!strcmp(word, "--")) // End of arguments. { return count; } else if(word[0]) // Make sure there *is* a word. { // Increase argument count. count++; if(mode != PM_COUNT) { // Allocate memory for the argument and copy it to the list. args[arg_pos] = malloc(strlen(word) + 1); strcpy(args[arg_pos++], word); } } } return count; }