/************************************************************************** Autocompletes the input line with a player or user name. Returns FALSE if there is no string to complete. **************************************************************************/ static bool chatline_autocomplete(GtkEditable *editable) { #define MAX_MATCHES 10 const char *name[MAX_MATCHES]; char buf[MAX_LEN_NAME * MAX_MATCHES]; gint pos; gchar *chars, *p, *prev; int num, i; size_t prefix_len; /* Part 1: get the string to complete. */ pos = gtk_editable_get_position(editable); chars = gtk_editable_get_chars(editable, 0, pos); p = chars + strlen(chars); while ((prev = g_utf8_find_prev_char(chars, p))) { if (!g_unichar_isalnum(g_utf8_get_char(prev))) { break; } p = prev; } /* p points to the start of the last word, or the start of the string. */ prefix_len = g_utf8_strlen(p, -1); if (0 == prefix_len) { /* Empty: nothing to complete, propagate the event. */ g_free(chars); return FALSE; } /* Part 2: compare with player and user names. */ num = check_player_or_user_name(p, name, MAX_MATCHES); if (1 == num) { gtk_editable_delete_text(editable, pos - prefix_len, pos); pos -= prefix_len; gtk_editable_insert_text(editable, name[0], strlen(name[0]), &pos); gtk_editable_set_position(editable, pos); g_free(chars); return TRUE; } else if (num > 1) { if (get_common_prefix(name, num, buf, sizeof(buf)) > prefix_len) { gtk_editable_delete_text(editable, pos - prefix_len, pos); pos -= prefix_len; gtk_editable_insert_text(editable, buf, strlen(buf), &pos); gtk_editable_set_position(editable, pos); } sz_strlcpy(buf, name[0]); for (i = 1; i < num; i++) { cat_snprintf(buf, sizeof(buf), ", %s", name[i]); } /* TRANS: comma-separated list of player/user names for completion */ output_window_printf(ftc_client, _("Suggestions: %s."), buf); } g_free(chars); return TRUE; }
void SkDiffContext::addDiff(const char* baselinePath, const char* testPath) { // Load the images at the paths SkBitmap baselineBitmap; SkBitmap testBitmap; if (!SkImageDecoder::DecodeFile(baselinePath, &baselineBitmap)) { SkDebugf("Failed to load bitmap \"%s\"\n", baselinePath); return; } if (!SkImageDecoder::DecodeFile(testPath, &testBitmap)) { SkDebugf("Failed to load bitmap \"%s\"\n", testPath); return; } // Setup a record for this diff fRecordMutex.acquire(); DiffRecord* newRecord = fRecords.addToHead(DiffRecord()); fRecordMutex.release(); // compute the common name SkString baseName = SkOSPath::Basename(baselinePath); SkString testName = SkOSPath::Basename(testPath); if (longNames) { newRecord->fCommonName = get_combined_name(baseName, testName); } else { newRecord->fCommonName = get_common_prefix(baseName, testName); } newRecord->fCommonName.append(".png"); newRecord->fBaselinePath = baselinePath; newRecord->fTestPath = testPath; newRecord->fSize = SkISize::Make(baselineBitmap.width(), baselineBitmap.height()); // only generate diff images if we have a place to store them SkImageDiffer::BitmapsToCreate bitmapsToCreate; bitmapsToCreate.alphaMask = !fAlphaMaskDir.isEmpty(); bitmapsToCreate.rgbDiff = !fRgbDiffDir.isEmpty(); bitmapsToCreate.whiteDiff = !fWhiteDiffDir.isEmpty(); // Perform each diff for (int differIndex = 0; differIndex < fDifferCount; differIndex++) { SkImageDiffer* differ = fDiffers[differIndex]; // Copy the results into data for this record DiffData& diffData = newRecord->fDiffs.push_back(); diffData.fDiffName = differ->getName(); if (!differ->diff(&baselineBitmap, &testBitmap, bitmapsToCreate, &diffData.fResult)) { // if the diff failed, record -1 as the result // TODO(djsollen): Record more detailed information about exactly what failed. // (Image dimension mismatch? etc.) See http://skbug.com/2710 ('make skpdiff // report more detail when it fails to compare two images') diffData.fResult.result = -1; continue; } if (bitmapsToCreate.alphaMask && SkImageDiffer::RESULT_CORRECT != diffData.fResult.result && !diffData.fResult.poiAlphaMask.empty() && !newRecord->fCommonName.isEmpty()) { newRecord->fAlphaMaskPath = SkOSPath::Join(fAlphaMaskDir.c_str(), newRecord->fCommonName.c_str()); // compute the image diff and output it SkBitmap copy; diffData.fResult.poiAlphaMask.copyTo(©, kN32_SkColorType); SkImageEncoder::EncodeFile(newRecord->fAlphaMaskPath.c_str(), copy, SkImageEncoder::kPNG_Type, 100); // cleanup the existing bitmap to free up resources; diffData.fResult.poiAlphaMask.reset(); bitmapsToCreate.alphaMask = false; } if (bitmapsToCreate.rgbDiff && SkImageDiffer::RESULT_CORRECT != diffData.fResult.result && !diffData.fResult.rgbDiffBitmap.empty() && !newRecord->fCommonName.isEmpty()) { // TODO(djsollen): Rather than taking the max r/g/b diffs that come back from // a particular differ and storing them as toplevel fields within // newRecord, we should extend outputRecords() to report optional // fields for each differ (not just "result" and "pointsOfInterest"). // See http://skbug.com/2712 ('allow skpdiff to report different sets // of result fields for different comparison algorithms') newRecord->fMaxRedDiff = diffData.fResult.maxRedDiff; newRecord->fMaxGreenDiff = diffData.fResult.maxGreenDiff; newRecord->fMaxBlueDiff = diffData.fResult.maxBlueDiff; newRecord->fRgbDiffPath = SkOSPath::Join(fRgbDiffDir.c_str(), newRecord->fCommonName.c_str()); SkImageEncoder::EncodeFile(newRecord->fRgbDiffPath.c_str(), diffData.fResult.rgbDiffBitmap, SkImageEncoder::kPNG_Type, 100); diffData.fResult.rgbDiffBitmap.reset(); bitmapsToCreate.rgbDiff = false; } if (bitmapsToCreate.whiteDiff && SkImageDiffer::RESULT_CORRECT != diffData.fResult.result && !diffData.fResult.whiteDiffBitmap.empty() && !newRecord->fCommonName.isEmpty()) { newRecord->fWhiteDiffPath = SkOSPath::Join(fWhiteDiffDir.c_str(), newRecord->fCommonName.c_str()); SkImageEncoder::EncodeFile(newRecord->fWhiteDiffPath.c_str(), diffData.fResult.whiteDiffBitmap, SkImageEncoder::kPNG_Type, 100); diffData.fResult.whiteDiffBitmap.reset(); bitmapsToCreate.whiteDiff = false; } } }