<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/bind.h"
#include "base/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "chrome/browser/character_encoding.h"
#include "chrome/browser/net/url_request_mock_util.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/test/net/url_request_mock_http_job.h"

using content::BrowserThread;

static const FilePath::CharType* kTestDir = FILE_PATH_LITERAL("encoding_tests");

class BrowserEncodingTest : public InProcessBrowserTest {
 protected:
  BrowserEncodingTest() {}

  // Saves the current page and verifies that the output matches the expected
  // result.
  void SaveAndCompare(const char* filename_to_write, const FilePath& expected) {
    // Dump the page, the content of dump page should be identical to the
    // expected result file.
    FilePath full_file_name = save_dir_.AppendASCII(filename_to_write);
    // We save the page as way of complete HTML file, which requires a directory
    // name to save sub resources in it. Although this test file does not have
    // sub resources, but the directory name is still required.
    content::WindowedNotificationObserver observer(
        content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED,
        content::NotificationService::AllSources());
    chrome::GetActiveWebContents(browser())->SavePage(
        full_file_name, temp_sub_resource_dir_,
        content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML);
    observer.Wait();

    FilePath expected_file_name = ui_test_utils::GetTestFilePath(
        FilePath(kTestDir), expected);

    EXPECT_TRUE(file_util::ContentsEqual(full_file_name, expected_file_name));
  }

  virtual void SetUpOnMainThread() OVERRIDE {
    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
    save_dir_ = temp_dir_.path();
    temp_sub_resource_dir_ = save_dir_.AppendASCII("sub_resource_files");

    BrowserThread::PostTask(
        BrowserThread::IO, FROM_HERE,
        base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
  }

  base::ScopedTempDir temp_dir_;
  FilePath save_dir_;
  FilePath temp_sub_resource_dir_;
};

// TODO(jnd): 1. Some encodings are missing here. It'll be added later. See
// http://crbug.com/13306.
// 2. Add more files with multiple encoding name variants for each canonical
// encoding name). Webkit layout tests cover some, but testing in the UI test is
// also necessary.
// SLOW_ is added for XP debug bots. These tests should really be unittests...
IN_PROC_BROWSER_TEST_F(BrowserEncodingTest, SLOW_TestEncodingAliasMapping) {
  struct EncodingTestData {
    const char* file_name;
    const char* encoding_name;
  };

  const EncodingTestData kEncodingTestDatas[] = {
    { "Big5.html", "Big5" },
    { "EUC-JP.html", "EUC-JP" },
    { "gb18030.html", "gb18030" },
    { "iso-8859-1.html", "ISO-8859-1" },
    { "ISO-8859-2.html", "ISO-8859-2" },
    { "ISO-8859-4.html", "ISO-8859-4" },
    { "ISO-8859-5.html", "ISO-8859-5" },
    { "ISO-8859-6.html", "ISO-8859-6" },
    { "ISO-8859-7.html", "ISO-8859-7" },
    { "ISO-8859-8.html", "ISO-8859-8" },
    { "ISO-8859-13.html", "ISO-8859-13" },
    { "ISO-8859-15.html", "ISO-8859-15" },
    { "KOI8-R.html", "KOI8-R" },
    { "KOI8-U.html", "KOI8-U" },
    { "macintosh.html", "macintosh" },
    { "Shift-JIS.html", "Shift_JIS" },
    { "US-ASCII.html", "ISO-8859-1" },  // http://crbug.com/15801
    { "UTF-8.html", "UTF-8" },
    { "UTF-16LE.html", "UTF-16LE" },
    { "windows-874.html", "windows-874" },
    // http://crbug.com/95963
    // { "windows-949.html", "windows-949" },
    { "windows-1250.html", "windows-1250" },
    { "windows-1251.html", "windows-1251" },
    { "windows-1252.html", "windows-1252" },
    { "windows-1253.html", "windows-1253" },
    { "windows-1254.html", "windows-1254" },
    { "windows-1255.html", "windows-1255" },
    { "windows-1256.html", "windows-1256" },
    { "windows-1257.html", "windows-1257" },
    { "windows-1258.html", "windows-1258" }
  };
  const char* const kAliasTestDir = "alias_mapping";

  FilePath test_dir_path = FilePath(kTestDir).AppendASCII(kAliasTestDir);
  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kEncodingTestDatas); ++i) {
    FilePath test_file_path(test_dir_path);
    test_file_path = test_file_path.AppendASCII(
        kEncodingTestDatas[i].file_name);

    GURL url = content::URLRequestMockHTTPJob::GetMockUrl(test_file_path);

    // When looping through all the above files in one WebContents, there's a
    // race condition on Windows trybots that causes the previous encoding to be
    // seen sometimes. Create a new tab for each one.  http://crbug.com/122053
    ui_test_utils::NavigateToURLWithDisposition(
        browser(), url, NEW_FOREGROUND_TAB,
        ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);

    EXPECT_EQ(kEncodingTestDatas[i].encoding_name,
              chrome::GetActiveWebContents(browser())->GetEncoding());
    chrome::CloseTab(browser());
  }
}

// Marked as flaky: see  http://crbug.com/44668
IN_PROC_BROWSER_TEST_F(BrowserEncodingTest, TestOverrideEncoding) {
  const char* const kTestFileName = "gb18030_with_iso88591_meta.html";
  const char* const kExpectedFileName =
      "expected_gb18030_saved_from_iso88591_meta.html";
  const char* const kOverrideTestDir = "user_override";

  FilePath test_dir_path = FilePath(kTestDir).AppendASCII(kOverrideTestDir);
  test_dir_path = test_dir_path.AppendASCII(kTestFileName);
  GURL url = content::URLRequestMockHTTPJob::GetMockUrl(test_dir_path);
  ui_test_utils::NavigateToURL(browser(), url);
  content::WebContents* web_contents = chrome::GetActiveWebContents(browser());
  EXPECT_EQ("ISO-8859-1", web_contents->GetEncoding());

  // Override the encoding to "gb18030".
  const std::string selected_encoding =
      CharacterEncoding::GetCanonicalEncodingNameByAliasName("gb18030");
  content::TestNavigationObserver navigation_observer(
      content::Source<content::NavigationController>(
          &web_contents->GetController()));
  web_contents->SetOverrideEncoding(selected_encoding);
  navigation_observer.Wait();
  EXPECT_EQ("gb18030", web_contents->GetEncoding());

  FilePath expected_filename =
      FilePath().AppendASCII(kOverrideTestDir).AppendASCII(kExpectedFileName);
  SaveAndCompare(kTestFileName, expected_filename);
}

// The following encodings are excluded from the auto-detection test because
// it's a known issue that the current encoding detector does not detect them:
// ISO-8859-4
// ISO-8859-13
// KOI8-U
// macintosh
// windows-874
// windows-1252
// windows-1253
// windows-1257
// windows-1258

// For Hebrew, the expected encoding value is ISO-8859-8-I. See
// http://crbug.com/2927 for more details.
//
// This test fails frequently on the win_rel trybot. See http://crbug.com/122053
#if defined(OS_WIN)
#define MAYBE_TestEncodingAutoDetect DISABLED_TestEncodingAutoDetect
#else
#define MAYBE_TestEncodingAutoDetect TestEncodingAutoDetect
#endif
IN_PROC_BROWSER_TEST_F(BrowserEncodingTest, MAYBE_TestEncodingAutoDetect) {
  struct EncodingAutoDetectTestData {
    const char* test_file_name;   // File name of test data.
    const char* expected_result;  // File name of expected results.
    const char* expected_encoding;   // expected encoding.
  };
  const EncodingAutoDetectTestData kTestDatas[] = {
      { "Big5_with_no_encoding_specified.html",
        "expected_Big5_saved_from_no_encoding_specified.html",
        "Big5" },
      { "gb18030_with_no_encoding_specified.html",
        "expected_gb18030_saved_from_no_encoding_specified.html",
        "gb18030" },
      { "iso-8859-1_with_no_encoding_specified.html",
        "expected_iso-8859-1_saved_from_no_encoding_specified.html",
        "ISO-8859-1" },
      { "ISO-8859-5_with_no_encoding_specified.html",
        "expected_ISO-8859-5_saved_from_no_encoding_specified.html",
        "ISO-8859-5" },
      { "ISO-8859-6_with_no_encoding_specified.html",
        "expected_ISO-8859-6_saved_from_no_encoding_specified.html",
        "ISO-8859-6" },
      { "ISO-8859-7_with_no_encoding_specified.html",
        "expected_ISO-8859-7_saved_from_no_encoding_specified.html",
        "ISO-8859-7" },
      { "ISO-8859-8_with_no_encoding_specified.html",
        "expected_ISO-8859-8_saved_from_no_encoding_specified.html",
        "ISO-8859-8-I" },
      { "KOI8-R_with_no_encoding_specified.html",
        "expected_KOI8-R_saved_from_no_encoding_specified.html",
        "KOI8-R" },
      { "Shift-JIS_with_no_encoding_specified.html",
        "expected_Shift-JIS_saved_from_no_encoding_specified.html",
        "Shift_JIS" },
      { "UTF-8_with_no_encoding_specified.html",
        "expected_UTF-8_saved_from_no_encoding_specified.html",
        "UTF-8" },
      { "windows-949_with_no_encoding_specified.html",
        "expected_windows-949_saved_from_no_encoding_specified.html",
        "windows-949-2000" },
      { "windows-1251_with_no_encoding_specified.html",
        "expected_windows-1251_saved_from_no_encoding_specified.html",
        "windows-1251" },
      { "windows-1254_with_no_encoding_specified.html",
        "expected_windows-1254_saved_from_no_encoding_specified.html",
        "windows-1254" },
      { "windows-1255_with_no_encoding_specified.html",
        "expected_windows-1255_saved_from_no_encoding_specified.html",
        "windows-1255" },
      { "windows-1256_with_no_encoding_specified.html",
        "expected_windows-1256_saved_from_no_encoding_specified.html",
        "windows-1256" }
    };
  const char* const kAutoDetectDir = "auto_detect";
  // Directory of the files of expected results.
  const char* const kExpectedResultDir = "expected_results";

  FilePath test_dir_path = FilePath(kTestDir).AppendASCII(kAutoDetectDir);

  // Set the default charset to one of encodings not supported by the current
  // auto-detector (Please refer to the above comments) to make sure we
  // incorrectly decode the page. Now we use ISO-8859-4.
  browser()->profile()->GetPrefs()->SetString(prefs::kDefaultCharset,
                                              "ISO-8859-4");

  content::WebContents* web_contents = chrome::GetActiveWebContents(browser());
  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestDatas); ++i) {
    // Disable auto detect if it is on.
    browser()->profile()->GetPrefs()->SetBoolean(
        prefs::kWebKitUsesUniversalDetector, false);

    FilePath test_file_path(test_dir_path);
    test_file_path = test_file_path.AppendASCII(kTestDatas[i].test_file_name);
    GURL url = content::URLRequestMockHTTPJob::GetMockUrl(test_file_path);
    ui_test_utils::NavigateToURL(browser(), url);

    // Get the encoding used for the page, it must be the default charset we
    // just set.
    EXPECT_EQ("ISO-8859-4", web_contents->GetEncoding());

    // Enable the encoding auto detection.
    browser()->profile()->GetPrefs()->SetBoolean(
        prefs::kWebKitUsesUniversalDetector, true);

    content::TestNavigationObserver observer(
        content::Source<content::NavigationController>(
            &web_contents->GetController()));
    chrome::Reload(browser(), CURRENT_TAB);
    observer.Wait();

    // Re-get the encoding of page. It should return the real encoding now.
    EXPECT_EQ(kTestDatas[i].expected_encoding, web_contents->GetEncoding());

    // Dump the page, the content of dump page should be equal with our expect
    // result file.
    FilePath expected_result_file_name =
        FilePath().AppendASCII(kAutoDetectDir).AppendASCII(kExpectedResultDir).
        AppendASCII(kTestDatas[i].expected_result);
    SaveAndCompare(kTestDatas[i].test_file_name, expected_result_file_name);
  }
}
<commit_msg>GTTF: Split BrowserEncodingTest.TestEncodingAliasMapping into smaller tests.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/bind.h"
#include "base/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "chrome/browser/character_encoding.h"
#include "chrome/browser/net/url_request_mock_util.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/test/net/url_request_mock_http_job.h"

namespace {

struct EncodingTestData {
  const char* file_name;
  const char* encoding_name;
};

const EncodingTestData kEncodingTestDatas[] = {
  { "Big5.html", "Big5" },
  { "EUC-JP.html", "EUC-JP" },
  { "gb18030.html", "gb18030" },
  { "iso-8859-1.html", "ISO-8859-1" },
  { "ISO-8859-2.html", "ISO-8859-2" },
  { "ISO-8859-4.html", "ISO-8859-4" },
  { "ISO-8859-5.html", "ISO-8859-5" },
  { "ISO-8859-6.html", "ISO-8859-6" },
  { "ISO-8859-7.html", "ISO-8859-7" },
  { "ISO-8859-8.html", "ISO-8859-8" },
  { "ISO-8859-13.html", "ISO-8859-13" },
  { "ISO-8859-15.html", "ISO-8859-15" },
  { "KOI8-R.html", "KOI8-R" },
  { "KOI8-U.html", "KOI8-U" },
  { "macintosh.html", "macintosh" },
  { "Shift-JIS.html", "Shift_JIS" },
  { "US-ASCII.html", "ISO-8859-1" },  // http://crbug.com/15801
  { "UTF-8.html", "UTF-8" },
  { "UTF-16LE.html", "UTF-16LE" },
  { "windows-874.html", "windows-874" },
  // http://crbug.com/95963
  // { "windows-949.html", "windows-949" },
  { "windows-1250.html", "windows-1250" },
  { "windows-1251.html", "windows-1251" },
  { "windows-1252.html", "windows-1252" },
  { "windows-1253.html", "windows-1253" },
  { "windows-1254.html", "windows-1254" },
  { "windows-1255.html", "windows-1255" },
  { "windows-1256.html", "windows-1256" },
  { "windows-1257.html", "windows-1257" },
  { "windows-1258.html", "windows-1258" }
};

}  // namespace

using content::BrowserThread;

static const FilePath::CharType* kTestDir = FILE_PATH_LITERAL("encoding_tests");

class BrowserEncodingTest
    : public InProcessBrowserTest,
      public testing::WithParamInterface<EncodingTestData> {
 protected:
  BrowserEncodingTest() {}

  // Saves the current page and verifies that the output matches the expected
  // result.
  void SaveAndCompare(const char* filename_to_write, const FilePath& expected) {
    // Dump the page, the content of dump page should be identical to the
    // expected result file.
    FilePath full_file_name = save_dir_.AppendASCII(filename_to_write);
    // We save the page as way of complete HTML file, which requires a directory
    // name to save sub resources in it. Although this test file does not have
    // sub resources, but the directory name is still required.
    content::WindowedNotificationObserver observer(
        content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED,
        content::NotificationService::AllSources());
    chrome::GetActiveWebContents(browser())->SavePage(
        full_file_name, temp_sub_resource_dir_,
        content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML);
    observer.Wait();

    FilePath expected_file_name = ui_test_utils::GetTestFilePath(
        FilePath(kTestDir), expected);

    EXPECT_TRUE(file_util::ContentsEqual(full_file_name, expected_file_name));
  }

  virtual void SetUpOnMainThread() OVERRIDE {
    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
    save_dir_ = temp_dir_.path();
    temp_sub_resource_dir_ = save_dir_.AppendASCII("sub_resource_files");

    BrowserThread::PostTask(
        BrowserThread::IO, FROM_HERE,
        base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
  }

  base::ScopedTempDir temp_dir_;
  FilePath save_dir_;
  FilePath temp_sub_resource_dir_;
};

// TODO(jnd): 1. Some encodings are missing here. It'll be added later. See
// http://crbug.com/13306.
// 2. Add more files with multiple encoding name variants for each canonical
// encoding name). Webkit layout tests cover some, but testing in the UI test is
// also necessary.
IN_PROC_BROWSER_TEST_P(BrowserEncodingTest, TestEncodingAliasMapping) {
  const char* const kAliasTestDir = "alias_mapping";

  FilePath test_dir_path = FilePath(kTestDir).AppendASCII(kAliasTestDir);
  FilePath test_file_path(test_dir_path);
  test_file_path = test_file_path.AppendASCII(
      GetParam().file_name);

  GURL url = content::URLRequestMockHTTPJob::GetMockUrl(test_file_path);
  ui_test_utils::NavigateToURL(browser(), url);
  EXPECT_EQ(GetParam().encoding_name,
            chrome::GetActiveWebContents(browser())->GetEncoding());
}

INSTANTIATE_TEST_CASE_P(EncodingAliases,
                        BrowserEncodingTest,
                        testing::ValuesIn(kEncodingTestDatas));

// Marked as flaky: see  http://crbug.com/44668
IN_PROC_BROWSER_TEST_F(BrowserEncodingTest, TestOverrideEncoding) {
  const char* const kTestFileName = "gb18030_with_iso88591_meta.html";
  const char* const kExpectedFileName =
      "expected_gb18030_saved_from_iso88591_meta.html";
  const char* const kOverrideTestDir = "user_override";

  FilePath test_dir_path = FilePath(kTestDir).AppendASCII(kOverrideTestDir);
  test_dir_path = test_dir_path.AppendASCII(kTestFileName);
  GURL url = content::URLRequestMockHTTPJob::GetMockUrl(test_dir_path);
  ui_test_utils::NavigateToURL(browser(), url);
  content::WebContents* web_contents = chrome::GetActiveWebContents(browser());
  EXPECT_EQ("ISO-8859-1", web_contents->GetEncoding());

  // Override the encoding to "gb18030".
  const std::string selected_encoding =
      CharacterEncoding::GetCanonicalEncodingNameByAliasName("gb18030");
  content::TestNavigationObserver navigation_observer(
      content::Source<content::NavigationController>(
          &web_contents->GetController()));
  web_contents->SetOverrideEncoding(selected_encoding);
  navigation_observer.Wait();
  EXPECT_EQ("gb18030", web_contents->GetEncoding());

  FilePath expected_filename =
      FilePath().AppendASCII(kOverrideTestDir).AppendASCII(kExpectedFileName);
  SaveAndCompare(kTestFileName, expected_filename);
}

// The following encodings are excluded from the auto-detection test because
// it's a known issue that the current encoding detector does not detect them:
// ISO-8859-4
// ISO-8859-13
// KOI8-U
// macintosh
// windows-874
// windows-1252
// windows-1253
// windows-1257
// windows-1258

// For Hebrew, the expected encoding value is ISO-8859-8-I. See
// http://crbug.com/2927 for more details.
//
// This test fails frequently on the win_rel trybot. See http://crbug.com/122053
#if defined(OS_WIN)
#define MAYBE_TestEncodingAutoDetect DISABLED_TestEncodingAutoDetect
#else
#define MAYBE_TestEncodingAutoDetect TestEncodingAutoDetect
#endif
// TODO(phajdan.jr): See if fix for http://crbug.com/122053 would help here.
IN_PROC_BROWSER_TEST_F(BrowserEncodingTest, MAYBE_TestEncodingAutoDetect) {
  struct EncodingAutoDetectTestData {
    const char* test_file_name;   // File name of test data.
    const char* expected_result;  // File name of expected results.
    const char* expected_encoding;   // expected encoding.
  };
  const EncodingAutoDetectTestData kTestDatas[] = {
      { "Big5_with_no_encoding_specified.html",
        "expected_Big5_saved_from_no_encoding_specified.html",
        "Big5" },
      { "gb18030_with_no_encoding_specified.html",
        "expected_gb18030_saved_from_no_encoding_specified.html",
        "gb18030" },
      { "iso-8859-1_with_no_encoding_specified.html",
        "expected_iso-8859-1_saved_from_no_encoding_specified.html",
        "ISO-8859-1" },
      { "ISO-8859-5_with_no_encoding_specified.html",
        "expected_ISO-8859-5_saved_from_no_encoding_specified.html",
        "ISO-8859-5" },
      { "ISO-8859-6_with_no_encoding_specified.html",
        "expected_ISO-8859-6_saved_from_no_encoding_specified.html",
        "ISO-8859-6" },
      { "ISO-8859-7_with_no_encoding_specified.html",
        "expected_ISO-8859-7_saved_from_no_encoding_specified.html",
        "ISO-8859-7" },
      { "ISO-8859-8_with_no_encoding_specified.html",
        "expected_ISO-8859-8_saved_from_no_encoding_specified.html",
        "ISO-8859-8-I" },
      { "KOI8-R_with_no_encoding_specified.html",
        "expected_KOI8-R_saved_from_no_encoding_specified.html",
        "KOI8-R" },
      { "Shift-JIS_with_no_encoding_specified.html",
        "expected_Shift-JIS_saved_from_no_encoding_specified.html",
        "Shift_JIS" },
      { "UTF-8_with_no_encoding_specified.html",
        "expected_UTF-8_saved_from_no_encoding_specified.html",
        "UTF-8" },
      { "windows-949_with_no_encoding_specified.html",
        "expected_windows-949_saved_from_no_encoding_specified.html",
        "windows-949-2000" },
      { "windows-1251_with_no_encoding_specified.html",
        "expected_windows-1251_saved_from_no_encoding_specified.html",
        "windows-1251" },
      { "windows-1254_with_no_encoding_specified.html",
        "expected_windows-1254_saved_from_no_encoding_specified.html",
        "windows-1254" },
      { "windows-1255_with_no_encoding_specified.html",
        "expected_windows-1255_saved_from_no_encoding_specified.html",
        "windows-1255" },
      { "windows-1256_with_no_encoding_specified.html",
        "expected_windows-1256_saved_from_no_encoding_specified.html",
        "windows-1256" }
    };
  const char* const kAutoDetectDir = "auto_detect";
  // Directory of the files of expected results.
  const char* const kExpectedResultDir = "expected_results";

  FilePath test_dir_path = FilePath(kTestDir).AppendASCII(kAutoDetectDir);

  // Set the default charset to one of encodings not supported by the current
  // auto-detector (Please refer to the above comments) to make sure we
  // incorrectly decode the page. Now we use ISO-8859-4.
  browser()->profile()->GetPrefs()->SetString(prefs::kDefaultCharset,
                                              "ISO-8859-4");

  content::WebContents* web_contents = chrome::GetActiveWebContents(browser());
  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestDatas); ++i) {
    // Disable auto detect if it is on.
    browser()->profile()->GetPrefs()->SetBoolean(
        prefs::kWebKitUsesUniversalDetector, false);

    FilePath test_file_path(test_dir_path);
    test_file_path = test_file_path.AppendASCII(kTestDatas[i].test_file_name);
    GURL url = content::URLRequestMockHTTPJob::GetMockUrl(test_file_path);
    ui_test_utils::NavigateToURL(browser(), url);

    // Get the encoding used for the page, it must be the default charset we
    // just set.
    EXPECT_EQ("ISO-8859-4", web_contents->GetEncoding());

    // Enable the encoding auto detection.
    browser()->profile()->GetPrefs()->SetBoolean(
        prefs::kWebKitUsesUniversalDetector, true);

    content::TestNavigationObserver observer(
        content::Source<content::NavigationController>(
            &web_contents->GetController()));
    chrome::Reload(browser(), CURRENT_TAB);
    observer.Wait();

    // Re-get the encoding of page. It should return the real encoding now.
    EXPECT_EQ(kTestDatas[i].expected_encoding, web_contents->GetEncoding());

    // Dump the page, the content of dump page should be equal with our expect
    // result file.
    FilePath expected_result_file_name =
        FilePath().AppendASCII(kAutoDetectDir).AppendASCII(kExpectedResultDir).
        AppendASCII(kTestDatas[i].expected_result);
    SaveAndCompare(kTestDatas[i].test_file_name, expected_result_file_name);
  }
}
<|endoftext|>


<commit_before>#include <iostream>
#include "menuinterface.h"

using namespace std;

MenuInterface::MenuInterface()
{
    _firstTimeBooting = 0;
}

void MenuInterface::invalidInput()
{
    cout << endl;
    cout << "Your input was invalid, please try again." << endl;
    cout << endl;
}

void MenuInterface::banner()
{
    //system("CLS");
    if(_firstTimeBooting == constants::FIRST_TIME)
    {
        cout << endl;
        cout << "       ********************************************" << endl;
        cout << "       *  WELCOME TO THE COMPUTER SCIENTIST LIST  *" << endl;
        cout << "       ********************************************" << endl;
        cout << endl;
        _firstTimeBooting = 1;//just something else than 0
    }
    else
    {
        cout << endl;
        cout << "       ********************************************" << endl;
        cout << "       *          COMPUTER SCIENTIST LIST         *" << endl;
        cout << "       ********************************************" << endl;
        cout << endl;
    }

}

void MenuInterface::DisplayMenu()
{
    string choice;

    while(choice != "Q" || choice != "q")
    {
        cout << "| 1 | Display either a computer or a scientist" << endl;
        cout << "| 2 | Search the list" << endl;
        cout << "| 3 | Add to the list" << endl;
        cout << "| 4 | Remove from the list" << endl;
        cout << "| Q | Exit the program" << endl;
        cout << "Enter your choice here: ";
        cin >> choice;
        cout << endl;

        if(choice == constants::DISPLAY_LIST || choice == constants::ADD || choice == constants::SEARCH || choice == constants::REMOVE)
        {
            processChoice(choice);
        }
        else if(choice == "Q" || choice == "q")
        {
            return;
        }
        else
        {
            invalidInput();
            banner();
            DisplayMenu();
        }
    }
}

string MenuInterface::subMenu()
{
    string subMenuChoice;
    do
    {
        cout << endl;
        cout << "Choose either:" << endl;
        cout << "| 1 | A computer " << endl;
        cout << "| 2 | A scientist " << endl;

        cin >> subMenuChoice;

        if(subMenuChoice == constants::COMPUTER || subMenuChoice == constants::SCIENTIST)
        {
            return subMenuChoice;
        }
        else
        {
            cout << endl;
            invalidInput();
            cout << endl;
        }
    }while(subMenuChoice != constants::COMPUTER || subMenuChoice != constants::SCIENTIST);

    return subMenuChoice;
}

void MenuInterface::processChoice(const string choice)
{
    string subMenuChoice = subMenu();
    int choiceInt = stoi(choice);
    banner();

    // Computer operations
    if(subMenuChoice == constants::COMPUTER)
    {
        switch (choiceInt)
        {
        case 1:
            //Display computer
            break;
        case 2:
            // Search for a computer"
            break;
        case 3:
            banner();
            _uL.addComputer();
        break;
        case 4:
            // Remove a computer
            break;
        default:
            invalidInput();
            break;
        }
    }

    // Scientist operations
    else if(subMenuChoice == constants::SCIENTIST)
    {
        switch (choiceInt)
        {
        case 1:
            displayScientists();
            break;
        case 2:
            _uL.searchForAPerson();
            break;
        case 3:
            _uL.addPerson();
        break;
        case 4:
            _uL.removePersonFromList();
            break;
        default:
            // This should never run
            invalidInput();
            break;
        }
    }
    else
    {
        // This should never run
        cout << "Something went wrong" << endl;
    }
}

void MenuInterface::displayScientists()
{
    string sortOption;
    _uL.printCompleteList();
    cout << "| 1 | Sort computer scientists by alphabetical order" << endl;
    cout << "| 2 | Sort computer scientists by ascending alphabetical order" << endl;
    cout << "| 3 | Sort computer scientists by year of birth" << endl;
    cout << "| 4 | Sort computer scientists by ascending year of birth" << endl;
    cout << "| 5 | Sort computer scientists by year of death" << endl;
    cout << "| 6 | Sort computer scientists by age" << endl;
    cout << "| 7 | Sort computer scientists by gender" << endl;
    cout << "| 0 | Go back" << endl;
    cout << "Enter your choice here: ";
    cin >> sortOption;
    cout << endl;

    if(sortOption == constants::SORT_ALPHABET)
    {
        banner();
        _uL.sortListAlphabetically();
    }
    else if(sortOption == constants::SORT_BY_YEAR_OF_BIRTH)
    {
        banner();
        _uL.sortListByBirthYear();
    }
    else if(sortOption == constants::SORT_BY_YEAR_OF_DEATH)
    {
        banner();
        _uL.sortListByDeathYear();
    }
    else if(sortOption == constants::SORT_BY_AGE)
    {
        banner();
        _uL.sortListByAge();
    }
    else if(sortOption == constants::SORT_ASCENDING_ALPHABET)
    {
        banner();
        _uL.sortListAlphabeticallyASC();
    }
    else if(sortOption == constants::SORT_BY_ASCENDING_YEAR_OF_BIRTH)
    {
        banner();
        _uL.sortListByBirthYearASC();
    }
    else if(sortOption == constants::SORT_BY_GENDER)
    {
        banner();
        _uL.sortListByGender();
    }
    else if(sortOption == constants::GO_BACK)
    {
        banner();
    }
    else
    {
        banner();
        invalidInput();
    }
}
<commit_msg>menuinterface<commit_after>#include <iostream>
#include "menuinterface.h"

using namespace std;

MenuInterface::MenuInterface()
{
    _firstTimeBooting = 0;
}

void MenuInterface::invalidInput()
{
    cout << endl;
    cout << "Your input was invalid, please try again." << endl;
    cout << endl;
}

void MenuInterface::banner()
{
    //system("CLS");
    if(_firstTimeBooting == constants::FIRST_TIME)
    {
        cout << endl;
        cout << "       ********************************************" << endl;
        cout << "       *  WELCOME TO THE COMPUTER SCIENTIST LIST  *" << endl;
        cout << "       ********************************************" << endl;
        cout << endl;
        _firstTimeBooting = 1;//just something else than 0
    }
    else
    {
        cout << endl;
        cout << "       ********************************************" << endl;
        cout << "       *          COMPUTER SCIENTIST LIST         *" << endl;
        cout << "       ********************************************" << endl;
        cout << endl;
    }

}

void MenuInterface::DisplayMenu()
{
    string choice;

    while(choice != "Q" || choice != "q")
    {
        cout << "| 1 | Display either a computer or a scientist" << endl;
        cout << "| 2 | Search the list" << endl;
        cout << "| 3 | Add to the list" << endl;
        cout << "| 4 | Remove from the list" << endl;
        cout << "| Q | Exit the program" << endl;
        cout << "Enter your choice here: ";
        cin >> choice;
        cout << endl;

        if(choice == constants::DISPLAY_LIST || choice == constants::ADD || choice == constants::SEARCH || choice == constants::REMOVE)
        {
            processChoice(choice);
        }
        else if(choice == "Q" || choice == "q")
        {
            char choice;
            cout << "Are you sure you want to quit the program?" << endl;
            cout << "Enter y for yes, and n for no: ";
            cin >> choice;
            if(choice != 'y' && choice != 'Y')
            {
                cout << endl;
                DisplayMenu();
            }
            else
            {
                return;
            }
        }
        else
        {
            invalidInput();
            banner();
            DisplayMenu();
        }
    }
}

string MenuInterface::subMenu()
{
    string subMenuChoice;
    do
    {
        cout << endl;
        cout << "Choose either:" << endl;
        cout << "| 1 | A computer " << endl;
        cout << "| 2 | A scientist " << endl;

        cin >> subMenuChoice;

        if(subMenuChoice == constants::COMPUTER || subMenuChoice == constants::SCIENTIST)
        {
            return subMenuChoice;
        }
        else
        {
            cout << endl;
            invalidInput();
            cout << endl;
        }
    }while(subMenuChoice != constants::COMPUTER || subMenuChoice != constants::SCIENTIST);

    return subMenuChoice;
}

void MenuInterface::processChoice(const string choice)
{
    string subMenuChoice = subMenu();
    int choiceInt = stoi(choice);
    banner();

    // Computer operations
    if(subMenuChoice == constants::COMPUTER)
    {
        switch (choiceInt)
        {
        case 1:
            //Display computer
            break;
        case 2:
            // Search for a computer"
            break;
        case 3:
            banner();
            _uL.addComputer();
        break;
        case 4:
            // Remove a computer
            break;
        default:
            invalidInput();
            break;
        }
    }

    // Scientist operations
    else if(subMenuChoice == constants::SCIENTIST)
    {
        switch (choiceInt)
        {
        case 1:
            displayScientists();
            break;
        case 2:
            _uL.searchForAPerson();
            break;
        case 3:
            _uL.addPerson();
        break;
        case 4:
            _uL.removePersonFromList();
            break;
        default:
            // This should never run
            invalidInput();
            break;
        }
    }
    else
    {
        // This should never run
        cout << "Something went wrong" << endl;
    }
}

void MenuInterface::displayScientists()
{
    string sortOption;
    _uL.printCompleteList();
    cout << "| 1 | Sort computer scientists by alphabetical order" << endl;
    cout << "| 2 | Sort computer scientists by ascending alphabetical order" << endl;
    cout << "| 3 | Sort computer scientists by year of birth" << endl;
    cout << "| 4 | Sort computer scientists by ascending year of birth" << endl;
    cout << "| 5 | Sort computer scientists by year of death" << endl;
    cout << "| 6 | Sort computer scientists by age" << endl;
    cout << "| 7 | Sort computer scientists by gender" << endl;
    cout << "| 0 | Go back" << endl;
    cout << "Enter your choice here: ";
    cin >> sortOption;
    cout << endl;

    if(sortOption == constants::SORT_ALPHABET)
    {
        banner();
        _uL.sortListAlphabetically();
    }
    else if(sortOption == constants::SORT_BY_YEAR_OF_BIRTH)
    {
        banner();
        _uL.sortListByBirthYear();
    }
    else if(sortOption == constants::SORT_BY_YEAR_OF_DEATH)
    {
        banner();
        _uL.sortListByDeathYear();
    }
    else if(sortOption == constants::SORT_BY_AGE)
    {
        banner();
        _uL.sortListByAge();
    }
    else if(sortOption == constants::SORT_ASCENDING_ALPHABET)
    {
        banner();
        _uL.sortListAlphabeticallyASC();
    }
    else if(sortOption == constants::SORT_BY_ASCENDING_YEAR_OF_BIRTH)
    {
        banner();
        _uL.sortListByBirthYearASC();
    }
    else if(sortOption == constants::SORT_BY_GENDER)
    {
        banner();
        _uL.sortListByGender();
    }
    else if(sortOption == constants::GO_BACK)
    {
        banner();
    }
    else
    {
        banner();
        invalidInput();
    }
}
<|endoftext|>


<commit_before>#include <gtest/gtest.h>
#include <SharedMemory.hpp>
#include <MMaper.hpp>
#include <Error.hpp>

//////////////////////////////////////////////////////////////////
TEST(MMaper, test_001)
{
     using namespace linux;
     posix::Name n("/ARTA");
     posix::OpenOptions f;
     posix::SharedMemory sm3(n, 4096, false, f);
     sm3.open().truncate();
     posix::MMapOptions mo;
     ASSERT_EQ(posix::mmap::READ |
	       posix::mmap::WRITE,
	       mo.get_protection().get());
     ASSERT_EQ(posix::mmap::MSHARED, mo.get_flag().get());
}

TEST(MMaper, test_002)
{
     using namespace linux;
     posix::Name n("/ARTA");
     posix::SharedMemory sm3(n, 4096, false);
     sm3.open().truncate();
     posix::MMapOptions mo;
     posix::MMaper m1(sm3, true, mo);
     posix::MMaper m2(sm3, true);
     posix::MMaper m3(sm3);
     try {
	  m3.unmap();
     } catch (linux::posix::NullPointer& d) {
	  ASSERT_TRUE(true);
	  return;
     }
     ASSERT_TRUE(false);
}

TEST(MMaper, test_003)
{
     using namespace linux;
     posix::Name n("/ARTA");
     posix::SharedMemory sm3(n, 4096, false);
     sm3.open().truncate();
     posix::MMaper m3(sm3);
     auto r = m3.map();
     ASSERT_EQ(4096, std::get<size_t>(r));
     ASSERT_NE(nullptr, std::get<void*>(r));
     m3.unmap();
}
//////////////////////////////////////////////////////////////////
<commit_msg>add unit test for MMaper::map(const size_t)<commit_after>#include <gtest/gtest.h>
#include <SharedMemory.hpp>
#include <MMaper.hpp>
#include <Error.hpp>

//////////////////////////////////////////////////////////////////
TEST(MMaper, test_001)
{
     using namespace linux;
     posix::Name n("/ARTA");
     posix::OpenOptions f;
     posix::SharedMemory sm3(n, 4096, false, f);
     sm3.open().truncate();
     posix::MMapOptions mo;
     ASSERT_EQ(posix::mmap::READ |
	       posix::mmap::WRITE,
	       mo.get_protection().get());
     ASSERT_EQ(posix::mmap::MSHARED, mo.get_flag().get());
}

TEST(MMaper, test_002)
{
     using namespace linux;
     posix::Name n("/ARTA");
     posix::SharedMemory sm3(n, 4096, false);
     sm3.open().truncate();
     posix::MMapOptions mo;
     posix::MMaper m1(sm3, true, mo);
     posix::MMaper m2(sm3, true);
     posix::MMaper m3(sm3);
     try {
	  m3.unmap();
     } catch (linux::posix::NullPointer& d) {
	  ASSERT_TRUE(true);
	  return;
     }
     ASSERT_TRUE(false);
}

TEST(MMaper, test_003)
{
     using namespace linux;
     posix::Name n("/ARTA");
     posix::SharedMemory sm3(n, 4096, false);
     sm3.open().truncate();
     posix::MMaper m3(sm3);
     auto r = m3.map();
     ASSERT_EQ(4096, std::get<size_t>(r));
     ASSERT_NE(nullptr, std::get<void*>(r));
     m3.unmap();
}

TEST(MMaper, test_004)
{
     using namespace linux;
     posix::Name n("/ARTA");
     posix::SharedMemory sm3(n, 4096, false);
     sm3.open().truncate();
     posix::MMaper m3(sm3);
     auto r = m3.map(512);
     ASSERT_EQ(512, std::get<size_t>(r));
     ASSERT_NE(nullptr, std::get<void*>(r));
     m3.unmap();
}
//////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>// sqlite_stmt.cpp
// sqlite statement library wrapper

// Copyright 2015 Matthew Chandler

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include "sqlite/sqlite.hpp"

#include "sqlite/sqlite_error.hpp"

// prepare a new statement for the given SQL
Sqlite_db_conn::Stmt::Stmt(const std::string & sql, Sqlite_db_conn & db):
    _db(db())
{
    int status = sqlite3_prepare_v2(db(), sql.c_str(), sql.length() + 1, &_stmt, NULL);

    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error(std::string("Error parsing SQL: ") + sqlite3_errmsg(db()), sql, status, _db);
    }
}

Sqlite_db_conn::Stmt::~Stmt()
{
    sqlite3_finalize(_stmt);
}

// bind NULL to var by index
void Sqlite_db_conn::Stmt::bind_null(const int index)
{
    int status = sqlite3_bind_null(_stmt, index);
    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error("Error binding index " +
            std::to_string(index) + ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// bind NULL to var by index
void Sqlite_db_conn::Stmt::bind(const int index)
{
    bind_null(index);
}

// bind double to var by index
void Sqlite_db_conn::Stmt::bind(const int index, const double val)
{
    int status = sqlite3_bind_double(_stmt, index, val);
    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error("Error binding index " +
            std::to_string(index) + ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// bind int to var by index
void Sqlite_db_conn::Stmt::bind(const int index, const int val)
{
    int status = sqlite3_bind_int(_stmt, index, val);
    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error("Error binding index " +
            std::to_string(index) + ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// bind sqlite3_int64 to var by index
void Sqlite_db_conn::Stmt::bind(const int index, const sqlite3_int64 val)
{
    int status = sqlite3_bind_int64(_stmt, index, val);
    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error("Error binding index " +
            std::to_string(index) + ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// bind std::string to var by index
void Sqlite_db_conn::Stmt::bind(const int index, const std::string & val)
{
    int status = sqlite3_bind_text(_stmt, index, val.c_str(), val.length(), SQLITE_TRANSIENT);
    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error("Error binding index " +
            std::to_string(index) + ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// bind sqlite3_value to var by index
void Sqlite_db_conn::Stmt::bind(const int index, const sqlite3_value * val)
{
    int status = sqlite3_bind_value(_stmt, index, val);
    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error("Error binding index " +
            std::to_string(index) + ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// bind null to var by name
void Sqlite_db_conn::Stmt::bind_null(const std::string & name)
{
    int status = sqlite3_bind_null(_stmt, bind_parameter_index(name));
    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error("Error binding " + name +
            ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// bind null to var by name
void Sqlite_db_conn::Stmt::bind(const std::string & name)
{
    bind_null(name);
}

// bind double to var by name
void Sqlite_db_conn::Stmt::bind(const std::string & name, const double val)
{
    int status = sqlite3_bind_double(_stmt, bind_parameter_index(name), val);
    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error("Error binding " + name +
            ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// bind int to var by name
void Sqlite_db_conn::Stmt::bind(const std::string & name, const int val)
{
    int status = sqlite3_bind_int(_stmt, bind_parameter_index(name), val);
    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error("Error binding " + name +
            ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// bind sqlite3_int64 to var by name
void Sqlite_db_conn::Stmt::bind(const std::string & name, const sqlite3_int64 val)
{
    int status = sqlite3_bind_int64(_stmt, bind_parameter_index(name), val);
    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error("Error binding " + name +
            ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// bind std::string to var by name
void Sqlite_db_conn::Stmt::bind(const std::string & name, const std::string & val)
{
    int status = sqlite3_bind_text(_stmt, bind_parameter_index(name), val.c_str(), val.length(), SQLITE_TRANSIENT);
    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error("Error binding " + name +
            ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// bind sqlite3_value to var by name
void Sqlite_db_conn::Stmt::bind(const std::string & name, const sqlite3_value * val)
{
    int status = sqlite3_bind_value(_stmt, bind_parameter_index(name), val);
    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error("Error binding " + name +
            ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// get bind var name from index
std::string Sqlite_db_conn::Stmt::bind_parameter_name(const int index)
{
    const char * name = sqlite3_bind_parameter_name(_stmt, index);
    if(!name)
    {
        throw Sqlite_logic_error("Error looking up bind var name for index " +
            std::to_string(index) + ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), SQLITE_ERROR, _db);
    }
    return std::string(name);
}

// get bind var index by name
int Sqlite_db_conn::Stmt::bind_parameter_index(const std::string & name)
{
    int index = sqlite3_bind_parameter_index(_stmt, name.c_str());
    if(!index)
    {
        throw Sqlite_logic_error("Error looking up index for bind var " +
            name + ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), SQLITE_ERROR, _db);
    }
    return index;
}

// run the statement. for multi-row SELECTs, fetches one row, and returns true when no rows remain
bool Sqlite_db_conn::Stmt::step()
{
    int status = sqlite3_step(_stmt);
    if(status == SQLITE_ROW)
    {
        return true;
    }
    else if(status == SQLITE_DONE)
    {
        return false;
    }
    else
    {
        throw Sqlite_logic_error(std::string("Error evaluating SQL: ") +
            sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// get SELECTed col as double
template<>
double Sqlite_db_conn::Stmt::get_col<double>(const int column)
{
    return sqlite3_column_double(_stmt, column);
}

// get SELECTed col as int
template<>
int Sqlite_db_conn::Stmt::get_col<int>(const int column)
{
    return sqlite3_column_int(_stmt, column);
}

// get SELECTed col as sqlite3_int64
template<>
sqlite3_int64 Sqlite_db_conn::Stmt::get_col<sqlite3_int64>(const int column)
{
    return sqlite3_column_int64(_stmt, column);
}

// get SELECTed col as std::string
template<>
std::string Sqlite_db_conn::Stmt::get_col<std::string>(const int column)
{
    const char * str = reinterpret_cast<const char *>(sqlite3_column_text(_stmt, column));

    if(!str)
        return std::string(); // empty str for NULL data
    else
        return std::string(str);
}

// get SELECTed col as const char *
template<>
const char * Sqlite_db_conn::Stmt::get_col<const char *>(const int column)
{
    return reinterpret_cast<const char *>(sqlite3_column_text(_stmt, column));
}

// get SELECTed col as sqlite3_value *
template<>
sqlite3_value * Sqlite_db_conn::Stmt::get_col<sqlite3_value *>(const int column)
{
    return sqlite3_column_value(_stmt, column);
}

// reset the statment - useful for INSERTing multiple rows
void Sqlite_db_conn::Stmt::reset()
{
    int status = sqlite3_reset(_stmt);
    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error(std::string("Error resetting statement: ") +
            sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// clear bind vars to NULL
void Sqlite_db_conn::Stmt::clear_bindings()
{
    sqlite3_clear_bindings(_stmt);
}

// get contained C obj (for use with C API - we don't wrap it all)
const sqlite3_stmt * Sqlite_db_conn::Stmt::operator()() const
{
    return _stmt;
}

sqlite3_stmt * Sqlite_db_conn::Stmt::operator()()
{
    return _stmt;
}
<commit_msg>use string literal suffix when beneficial<commit_after>// sqlite_stmt.cpp
// sqlite statement library wrapper

// Copyright 2015 Matthew Chandler

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include "sqlite/sqlite.hpp"

#include "sqlite/sqlite_error.hpp"

using namespace std::string_literals;

// prepare a new statement for the given SQL
Sqlite_db_conn::Stmt::Stmt(const std::string & sql, Sqlite_db_conn & db):
    _db(db())
{
    int status = sqlite3_prepare_v2(db(), sql.c_str(), sql.length() + 1, &_stmt, NULL);

    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error("Error parsing SQL: "s + sqlite3_errmsg(db()), sql, status, _db);
    }
}

Sqlite_db_conn::Stmt::~Stmt()
{
    sqlite3_finalize(_stmt);
}

// bind NULL to var by index
void Sqlite_db_conn::Stmt::bind_null(const int index)
{
    int status = sqlite3_bind_null(_stmt, index);
    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error("Error binding index " +
            std::to_string(index) + ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// bind NULL to var by index
void Sqlite_db_conn::Stmt::bind(const int index)
{
    bind_null(index);
}

// bind double to var by index
void Sqlite_db_conn::Stmt::bind(const int index, const double val)
{
    int status = sqlite3_bind_double(_stmt, index, val);
    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error("Error binding index " +
            std::to_string(index) + ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// bind int to var by index
void Sqlite_db_conn::Stmt::bind(const int index, const int val)
{
    int status = sqlite3_bind_int(_stmt, index, val);
    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error("Error binding index " +
            std::to_string(index) + ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// bind sqlite3_int64 to var by index
void Sqlite_db_conn::Stmt::bind(const int index, const sqlite3_int64 val)
{
    int status = sqlite3_bind_int64(_stmt, index, val);
    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error("Error binding index " +
            std::to_string(index) + ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// bind std::string to var by index
void Sqlite_db_conn::Stmt::bind(const int index, const std::string & val)
{
    int status = sqlite3_bind_text(_stmt, index, val.c_str(), val.length(), SQLITE_TRANSIENT);
    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error("Error binding index " +
            std::to_string(index) + ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// bind sqlite3_value to var by index
void Sqlite_db_conn::Stmt::bind(const int index, const sqlite3_value * val)
{
    int status = sqlite3_bind_value(_stmt, index, val);
    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error("Error binding index " +
            std::to_string(index) + ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// bind null to var by name
void Sqlite_db_conn::Stmt::bind_null(const std::string & name)
{
    int status = sqlite3_bind_null(_stmt, bind_parameter_index(name));
    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error("Error binding " + name +
            ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// bind null to var by name
void Sqlite_db_conn::Stmt::bind(const std::string & name)
{
    bind_null(name);
}

// bind double to var by name
void Sqlite_db_conn::Stmt::bind(const std::string & name, const double val)
{
    int status = sqlite3_bind_double(_stmt, bind_parameter_index(name), val);
    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error("Error binding " + name +
            ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// bind int to var by name
void Sqlite_db_conn::Stmt::bind(const std::string & name, const int val)
{
    int status = sqlite3_bind_int(_stmt, bind_parameter_index(name), val);
    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error("Error binding " + name +
            ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// bind sqlite3_int64 to var by name
void Sqlite_db_conn::Stmt::bind(const std::string & name, const sqlite3_int64 val)
{
    int status = sqlite3_bind_int64(_stmt, bind_parameter_index(name), val);
    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error("Error binding " + name +
            ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// bind std::string to var by name
void Sqlite_db_conn::Stmt::bind(const std::string & name, const std::string & val)
{
    int status = sqlite3_bind_text(_stmt, bind_parameter_index(name), val.c_str(), val.length(), SQLITE_TRANSIENT);
    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error("Error binding " + name +
            ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// bind sqlite3_value to var by name
void Sqlite_db_conn::Stmt::bind(const std::string & name, const sqlite3_value * val)
{
    int status = sqlite3_bind_value(_stmt, bind_parameter_index(name), val);
    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error("Error binding " + name +
            ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// get bind var name from index
std::string Sqlite_db_conn::Stmt::bind_parameter_name(const int index)
{
    const char * name = sqlite3_bind_parameter_name(_stmt, index);
    if(!name)
    {
        throw Sqlite_logic_error("Error looking up bind var name for index " +
            std::to_string(index) + ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), SQLITE_ERROR, _db);
    }
    return std::string(name);
}

// get bind var index by name
int Sqlite_db_conn::Stmt::bind_parameter_index(const std::string & name)
{
    int index = sqlite3_bind_parameter_index(_stmt, name.c_str());
    if(!index)
    {
        throw Sqlite_logic_error("Error looking up index for bind var " +
            name + ": " + sqlite3_errmsg(_db), sqlite3_sql(_stmt), SQLITE_ERROR, _db);
    }
    return index;
}

// run the statement. for multi-row SELECTs, fetches one row, and returns true when no rows remain
bool Sqlite_db_conn::Stmt::step()
{
    int status = sqlite3_step(_stmt);
    if(status == SQLITE_ROW)
    {
        return true;
    }
    else if(status == SQLITE_DONE)
    {
        return false;
    }
    else
    {
        throw Sqlite_logic_error("Error evaluating SQL: "s +
            sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// get SELECTed col as double
template<>
double Sqlite_db_conn::Stmt::get_col<double>(const int column)
{
    return sqlite3_column_double(_stmt, column);
}

// get SELECTed col as int
template<>
int Sqlite_db_conn::Stmt::get_col<int>(const int column)
{
    return sqlite3_column_int(_stmt, column);
}

// get SELECTed col as sqlite3_int64
template<>
sqlite3_int64 Sqlite_db_conn::Stmt::get_col<sqlite3_int64>(const int column)
{
    return sqlite3_column_int64(_stmt, column);
}

// get SELECTed col as std::string
template<>
std::string Sqlite_db_conn::Stmt::get_col<std::string>(const int column)
{
    const char * str = reinterpret_cast<const char *>(sqlite3_column_text(_stmt, column));

    if(!str)
        return ""s; // empty str for NULL data
    else
        return std::string(str);
}

// get SELECTed col as const char *
template<>
const char * Sqlite_db_conn::Stmt::get_col<const char *>(const int column)
{
    return reinterpret_cast<const char *>(sqlite3_column_text(_stmt, column));
}

// get SELECTed col as sqlite3_value *
template<>
sqlite3_value * Sqlite_db_conn::Stmt::get_col<sqlite3_value *>(const int column)
{
    return sqlite3_column_value(_stmt, column);
}

// reset the statment - useful for INSERTing multiple rows
void Sqlite_db_conn::Stmt::reset()
{
    int status = sqlite3_reset(_stmt);
    if(status != SQLITE_OK)
    {
        throw Sqlite_logic_error("Error resetting statement: "s +
            sqlite3_errmsg(_db), sqlite3_sql(_stmt), status, _db);
    }
}

// clear bind vars to NULL
void Sqlite_db_conn::Stmt::clear_bindings()
{
    sqlite3_clear_bindings(_stmt);
}

// get contained C obj (for use with C API - we don't wrap it all)
const sqlite3_stmt * Sqlite_db_conn::Stmt::operator()() const
{
    return _stmt;
}

sqlite3_stmt * Sqlite_db_conn::Stmt::operator()()
{
    return _stmt;
}
<|endoftext|>


<commit_before>#include "../canusb.hpp"
#include "xpcc/driver/can/canusb/canusb_formater.hpp"
#include <xpcc/architecture/driver.hpp>
#include <xpcc/workflow/timeout.hpp>
#include <iostream>

xpcc::CanUsb::CanUsb():
active(false),serialPort()
{

}

xpcc::CanUsb::~CanUsb(
)
{
	if(this->active)
	{
		{

			MutexGuard stateGuard( this->stateLock);
			this->active=false;
		}
		this->thread->join();
		delete this->thread;
		this->thread = 0;
	}
	this->serialPort.close();
	while(this->serialPort.isOpen()){
		//wait for port to close;
	}
}

bool xpcc::CanUsb::open(std::string deviceName, unsigned int baudRate))
{
	if(this->serialPort.isOpen()) this->serialPort.close();
	if (this->serialPort.open(deviceName, baudRate))
	{
		this->serialPort.clearWriteBuffer();
		this->serialPort.clearReadBuffer();
		this->serialPort.write("C\r");
		char a;
		xpcc::timeout<> timer;
		timer.restart(500);
		while(!this->serialPort.read(a)){
			if(timer.isExpired())
			{
				std::cout<< "Timer expired"<<std::endl;
				this->serialPort.close();
				return false;
			}
		}
		this->serialPort.write("S4\r");
		timer.restart(500);
		while(!this->serialPort.read(a)){
			if(timer.isExpired())
			{
				std::cout<< "Timer expired"<<std::endl;
				this->serialPort.close();
				return false;
			}
		}
		if( a != '\r') return false;
		this->serialPort.write("O\r");
		timer.restart(500);
		while(!this->serialPort.read(a))
		{
			if(timer.isExpired())
			{
				std::cout<< "Timer expired"<<std::endl;
				this->serialPort.close();
				return false;
			}
		}
		if(a != '\r') return false;
		{
			MutexGuard stateGuard( this->stateLock);
			this->active=true;
		}
		this->thread = new boost::thread(boost::bind(&xpcc::CanUsb::update, this));
		return true;
	}
	else
		return false;
};

void xpcc::CanUsb::close()
{
	{
		MutexGuard stateGuard( this->stateLock);
		this->active=false;
	}
	this->thread->join();
	delete this->thread;
	this->thread = 0;
	this->serialPort.close();
};

bool
xpcc::CanUsb::getMessage(can::Message& message)
{
	if(!this->readBuffer.empty())
	{
		message = this->readBuffer.front();
		this->readBuffer.pop();
		return true;
	}
	else{
		return false;
	}
};

bool
xpcc::CanUsb::sendMessage(const can::Message& message)
{	char str[128];
	xpcc::CanUsbFormater::convertToString(message, str);
	this->serialPort.write(str);
	return true;
}

void
xpcc::CanUsb::update()
{
	while(true)
	{
		char a;
		if(this->serialPort.read(a)){
			if(a == 'T' || a == 't' || a == 'r' || a == 'R'){
				this->tmpRead.clear();
				this->tmpRead += a;
			}
			else{
				this->tmpRead += a;
			}

			can::Message message;
			if(xpcc::CanUsbFormater::convertToCanMessage(this->tmpRead.c_str(), message))
			{
				this->readBuffer.push(message);
			}
		}
		if(!this->active) break;
	}
}

<commit_msg>small bug<commit_after>#include "../canusb.hpp"
#include "xpcc/driver/can/canusb/canusb_formater.hpp"
#include <xpcc/architecture/driver.hpp>
#include <xpcc/workflow/timeout.hpp>
#include <iostream>

xpcc::CanUsb::CanUsb():
active(false),serialPort()
{

}

xpcc::CanUsb::~CanUsb(
)
{
	if(this->active)
	{
		{

			MutexGuard stateGuard( this->stateLock);
			this->active=false;
		}
		this->thread->join();
		delete this->thread;
		this->thread = 0;
	}
	this->serialPort.close();
	while(this->serialPort.isOpen()){
		//wait for port to close;
	}
}

bool xpcc::CanUsb::open(std::string deviceName, unsigned int baudRate)
{
	if(this->serialPort.isOpen()) this->serialPort.close();
	if (this->serialPort.open(deviceName, baudRate))
	{
		this->serialPort.clearWriteBuffer();
		this->serialPort.clearReadBuffer();
		this->serialPort.write("C\r");
		char a;
		xpcc::timeout<> timer;
		timer.restart(500);
		while(!this->serialPort.read(a)){
			if(timer.isExpired())
			{
				std::cout<< "Timer expired"<<std::endl;
				this->serialPort.close();
				return false;
			}
		}
		this->serialPort.write("S4\r");
		timer.restart(500);
		while(!this->serialPort.read(a)){
			if(timer.isExpired())
			{
				std::cout<< "Timer expired"<<std::endl;
				this->serialPort.close();
				return false;
			}
		}
		if( a != '\r') return false;
		this->serialPort.write("O\r");
		timer.restart(500);
		while(!this->serialPort.read(a))
		{
			if(timer.isExpired())
			{
				std::cout<< "Timer expired"<<std::endl;
				this->serialPort.close();
				return false;
			}
		}
		if(a != '\r') return false;
		{
			MutexGuard stateGuard( this->stateLock);
			this->active=true;
		}
		this->thread = new boost::thread(boost::bind(&xpcc::CanUsb::update, this));
		return true;
	}
	else
		return false;
};

void xpcc::CanUsb::close()
{
	{
		MutexGuard stateGuard( this->stateLock);
		this->active=false;
	}
	this->thread->join();
	delete this->thread;
	this->thread = 0;
	this->serialPort.close();
};

bool
xpcc::CanUsb::getMessage(can::Message& message)
{
	if(!this->readBuffer.empty())
	{
		message = this->readBuffer.front();
		this->readBuffer.pop();
		return true;
	}
	else{
		return false;
	}
};

bool
xpcc::CanUsb::sendMessage(const can::Message& message)
{	char str[128];
	xpcc::CanUsbFormater::convertToString(message, str);
	this->serialPort.write(str);
	return true;
}

void
xpcc::CanUsb::update()
{
	while(true)
	{
		char a;
		if(this->serialPort.read(a)){
			if(a == 'T' || a == 't' || a == 'r' || a == 'R'){
				this->tmpRead.clear();
				this->tmpRead += a;
			}
			else{
				this->tmpRead += a;
			}

			can::Message message;
			if(xpcc::CanUsbFormater::convertToCanMessage(this->tmpRead.c_str(), message))
			{
				this->readBuffer.push(message);
			}
		}
		if(!this->active) break;
	}
}

<|endoftext|>


<commit_before>// Copyright (c) 2005-2009 Jaroslav Gresula
//
// Distributed under the MIT license (See accompanying file
// LICENSE.txt or copy at http://jagpdf.org/LICENSE.txt)
//

#include "precompiled.h"
#include <resources/typeman/truetype/ttfont.h>
#include <resources/typeman/truetype/ttfontmaker.h>
#include <resources/typeman/truetype/ttstructs.h>
#include <resources/interfaces/typeface.h>
#include <core/generic/null_deleter.h>
#include <core/generic/assert.h>
#include <core/jstd/tracer.h>
#include <map>

using namespace boost::integer;

namespace jag {
namespace resources {
namespace truetype {

namespace
{
  // composite glyph flags
  enum {
      ARG_1_AND_2_ARE_WORDS        = 1u << 0,
      WE_HAVE_A_SCALE            = 1u << 3,
      MORE_COMPONENTS            = 1u << 5,
      WE_HAVE_AN_X_AND_Y_SCALE    = 1u << 6,
      WE_HAVE_A_TWO_BY_TWO        = 1u << 7
  };
}

//////////////////////////////////////////////////////////////////////////
TTFont::TTFont(IStreamInput& font_data)
    : m_ttparser(font_data)
    , m_font(&font_data, &null_deleter)
{
}

//////////////////////////////////////////////////////////////////////////
void TTFont::make_subset(ISeqStreamOutput& subset_font,
                         UsedGlyphs const& used_glyphs,
                         bool include_cmap)
{
    TTFontMaker font_maker;
    font_maker.set_codepoint_to_glyph(used_glyphs.codepoint_to_glyph());

    // Iterate over the used glyphs and insert them to fontmaker. Construct
    // additonal_glyphs for those referenced from composite glyphs.
    typedef std::set<UInt16> Glyphs;
    Glyphs additional_glyphs;
    typedef UsedGlyphs::Glyphs::const_iterator GlyphIterator;
    GlyphIterator end = used_glyphs.glyphs_end();
    for(GlyphIterator it = used_glyphs.glyphs_begin(); it!=end; ++it)
    {
        // load the glyph and add it to font maker
        m_ttparser.load_glyph(*it);
        font_maker.add_glyph(m_ttparser.current_glyph_data(),
                             m_ttparser.current_glyph_size(),
                             *it);

        // inspect the glyph
        if (m_ttparser.current_glyph_size())
        {
            tt_glyph_data const* glyph_data =
                static_cast<tt_glyph_data const*>(m_ttparser.current_glyph_data());

            // is it a composite glyph?
            if (static_cast<short>(glyph_data->m_number_of_contours) < 0)
            {
                Byte const* curr =
                    static_cast<Byte const*>(m_ttparser.current_glyph_data()) + sizeof(tt_glyph_data);

                unsigned short flags;
                do {
                    flags = static_cast<unsigned short>(*reinterpret_cast<ubig16_t const*>(curr));
                    ubig16_t const* c_glyph_index = reinterpret_cast<ubig16_t const*>(curr+2);
                    curr += 4;

                    // verify that the glyph is not already in the passed set,
                    if (!used_glyphs.glyphs().count(*c_glyph_index))
                        additional_glyphs.insert(*c_glyph_index);

                    curr += flags & ARG_1_AND_2_ARE_WORDS ? 4 : 2;
                    if (flags & WE_HAVE_A_SCALE)
                        curr += 2;

                    if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
                        curr += 4;

                    if (flags & WE_HAVE_A_TWO_BY_TWO)
                        curr += 8;
                }
                while(flags & MORE_COMPONENTS);
            }
        }
    }

    if (!additional_glyphs.empty())
    {
        // upload the additional glyphs to fontmaker
        Glyphs::iterator endg = additional_glyphs.end();
        for(Glyphs::iterator it = additional_glyphs.begin(); it!=endg; ++it)
        {
            m_ttparser.load_glyph(*it);
            font_maker.add_glyph(m_ttparser.current_glyph_data(),
                                 m_ttparser.current_glyph_size(),
                                 *it);
        }
    }

    // The subset can contain no outlines, i.e it for instance could have only
    // spaces with varying widths. In such case the .notdef glyph (index 0) is
    // added to the subset. Otherwise, a missing glyf table causes problems for
    // e.g. Reader or certain FreeType versions.
    if (!font_maker.has_outlines())
    {
        // search through the first 255 glyph slots for one with glyph outlines
        UInt16 i = 0;
        for(; i<255; ++i)
        {
            m_ttparser.load_glyph(i);
            if (m_ttparser.current_glyph_size())
            {
                font_maker.add_glyph(m_ttparser.current_glyph_data(),
                                     m_ttparser.current_glyph_size(),
                                     i);
                break;
            }
        }

        if (i > 255) {
            TRACE_WRN << "font subset has an empty glyph table";
        }
    }

    TTFontParser::TableData table_data(m_ttparser.load_table(TT_MAXP));
    font_maker.add_table(TT_MAXP, table_data.first, table_data.second);

    table_data = m_ttparser.load_table(TT_HEAD);
    font_maker.add_table(TT_HEAD, table_data.first, table_data.second);

    // spec (5.8) says that name, os2 and post should not be needed
    // but when really removed Acrobat does not behave well
    const int num_const_tables = 8;
    const TTTableType const_tables[num_const_tables] = {
        TT_NAME, TT_OS2, TT_CVT, TT_FPGM, TT_PREP, TT_HHEA, TT_HMTX, TT_POST
    };

    for (int i=0; i<num_const_tables; ++i)
    {
        TTFontParser::TableData tdata(m_ttparser.load_table(const_tables[i]));
        if (tdata.first)
            font_maker.add_table(const_tables[i], tdata.first, tdata.second);
    }

    // to FontMaker::add_glyph() signature
    font_maker.output(subset_font, include_cmap);
}

//////////////////////////////////////////////////////////////////////////
std::pair<void const*,size_t> TTFont::dbg_load_glyph(UInt codepoint)
{
    unsigned gid = m_ttparser.charcode_to_glyph_index(codepoint);
    m_ttparser.load_glyph(gid);
    return std::make_pair(
          m_ttparser.current_glyph_data()
        , m_ttparser.current_glyph_size()
   );
}

//////////////////////////////////////////////////////////////////////////
Char const* TTFont::postscript_name()
{
    return m_ttparser.postscript_name();
}

}}} // namespace jag::resources::truetype

<commit_msg>fixed invalid condition<commit_after>// Copyright (c) 2005-2009 Jaroslav Gresula
//
// Distributed under the MIT license (See accompanying file
// LICENSE.txt or copy at http://jagpdf.org/LICENSE.txt)
//

#include "precompiled.h"
#include <resources/typeman/truetype/ttfont.h>
#include <resources/typeman/truetype/ttfontmaker.h>
#include <resources/typeman/truetype/ttstructs.h>
#include <resources/interfaces/typeface.h>
#include <core/generic/null_deleter.h>
#include <core/generic/assert.h>
#include <core/jstd/tracer.h>
#include <map>

using namespace boost::integer;

namespace jag {
namespace resources {
namespace truetype {

namespace
{
  // composite glyph flags
  enum {
      ARG_1_AND_2_ARE_WORDS        = 1u << 0,
      WE_HAVE_A_SCALE            = 1u << 3,
      MORE_COMPONENTS            = 1u << 5,
      WE_HAVE_AN_X_AND_Y_SCALE    = 1u << 6,
      WE_HAVE_A_TWO_BY_TWO        = 1u << 7
  };
}

//////////////////////////////////////////////////////////////////////////
TTFont::TTFont(IStreamInput& font_data)
    : m_ttparser(font_data)
    , m_font(&font_data, &null_deleter)
{
}

//////////////////////////////////////////////////////////////////////////
void TTFont::make_subset(ISeqStreamOutput& subset_font,
                         UsedGlyphs const& used_glyphs,
                         bool include_cmap)
{
    TTFontMaker font_maker;
    font_maker.set_codepoint_to_glyph(used_glyphs.codepoint_to_glyph());

    // Iterate over the used glyphs and insert them to fontmaker. Construct
    // additonal_glyphs for those referenced from composite glyphs.
    typedef std::set<UInt16> Glyphs;
    Glyphs additional_glyphs;
    typedef UsedGlyphs::Glyphs::const_iterator GlyphIterator;
    GlyphIterator end = used_glyphs.glyphs_end();
    for(GlyphIterator it = used_glyphs.glyphs_begin(); it!=end; ++it)
    {
        // load the glyph and add it to font maker
        m_ttparser.load_glyph(*it);
        font_maker.add_glyph(m_ttparser.current_glyph_data(),
                             m_ttparser.current_glyph_size(),
                             *it);

        // inspect the glyph
        if (m_ttparser.current_glyph_size())
        {
            tt_glyph_data const* glyph_data =
                static_cast<tt_glyph_data const*>(m_ttparser.current_glyph_data());

            // is it a composite glyph?
            if (static_cast<short>(glyph_data->m_number_of_contours) < 0)
            {
                Byte const* curr =
                    static_cast<Byte const*>(m_ttparser.current_glyph_data()) + sizeof(tt_glyph_data);

                unsigned short flags;
                do {
                    flags = static_cast<unsigned short>(*reinterpret_cast<ubig16_t const*>(curr));
                    ubig16_t const* c_glyph_index = reinterpret_cast<ubig16_t const*>(curr+2);
                    curr += 4;

                    // verify that the glyph is not already in the passed set,
                    if (!used_glyphs.glyphs().count(*c_glyph_index))
                        additional_glyphs.insert(*c_glyph_index);

                    curr += flags & ARG_1_AND_2_ARE_WORDS ? 4 : 2;
                    if (flags & WE_HAVE_A_SCALE)
                        curr += 2;

                    if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
                        curr += 4;

                    if (flags & WE_HAVE_A_TWO_BY_TWO)
                        curr += 8;
                }
                while(flags & MORE_COMPONENTS);
            }
        }
    }

    if (!additional_glyphs.empty())
    {
        // upload the additional glyphs to fontmaker
        Glyphs::iterator endg = additional_glyphs.end();
        for(Glyphs::iterator it = additional_glyphs.begin(); it!=endg; ++it)
        {
            m_ttparser.load_glyph(*it);
            font_maker.add_glyph(m_ttparser.current_glyph_data(),
                                 m_ttparser.current_glyph_size(),
                                 *it);
        }
    }

    // The subset can contain no outlines, i.e it for instance could have only
    // spaces with varying widths. In such case the .notdef glyph (index 0) is
    // added to the subset. Otherwise, a missing glyf table causes problems for
    // e.g. Reader or certain FreeType versions.
    if (!font_maker.has_outlines())
    {
        // search through the first 255 glyph slots for one with glyph outlines
        UInt16 i = 0;
        const UInt16 NGLYPHS = 255;
        for(; i < NGLYPHS; ++i)
        {
            m_ttparser.load_glyph(i);
            if (m_ttparser.current_glyph_size())
            {
                font_maker.add_glyph(m_ttparser.current_glyph_data(),
                                     m_ttparser.current_glyph_size(),
                                     i);
                break;
            }
        }

        if (i >= NGLYPHS) {
            TRACE_WRN << "font subset has an empty glyph table";
        }
    }

    TTFontParser::TableData table_data(m_ttparser.load_table(TT_MAXP));
    font_maker.add_table(TT_MAXP, table_data.first, table_data.second);

    table_data = m_ttparser.load_table(TT_HEAD);
    font_maker.add_table(TT_HEAD, table_data.first, table_data.second);

    // spec (5.8) says that name, os2 and post should not be needed
    // but when really removed Acrobat does not behave well
    const int num_const_tables = 8;
    const TTTableType const_tables[num_const_tables] = {
        TT_NAME, TT_OS2, TT_CVT, TT_FPGM, TT_PREP, TT_HHEA, TT_HMTX, TT_POST
    };

    for (int i=0; i<num_const_tables; ++i)
    {
        TTFontParser::TableData tdata(m_ttparser.load_table(const_tables[i]));
        if (tdata.first)
            font_maker.add_table(const_tables[i], tdata.first, tdata.second);
    }

    // to FontMaker::add_glyph() signature
    font_maker.output(subset_font, include_cmap);
}

//////////////////////////////////////////////////////////////////////////
std::pair<void const*,size_t> TTFont::dbg_load_glyph(UInt codepoint)
{
    unsigned gid = m_ttparser.charcode_to_glyph_index(codepoint);
    m_ttparser.load_glyph(gid);
    return std::make_pair(
          m_ttparser.current_glyph_data()
        , m_ttparser.current_glyph_size()
   );
}

//////////////////////////////////////////////////////////////////////////
Char const* TTFont::postscript_name()
{
    return m_ttparser.postscript_name();
}

}}} // namespace jag::resources::truetype

<|endoftext|>


<commit_before>/*
    Class that auto configures link-local xmpp account
    Copyright (C) 2011  Martin Klapetek <martin.klapetek@gmail.com>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "salut-enabler.h"

#include <TelepathyQt/ConnectionManager>
#include <TelepathyQt/ProfileManager>
#include <TelepathyQt/AccountManager>
#include <TelepathyQt/PendingOperation>
#include <TelepathyQt/PendingReady>
#include <TelepathyQt/PendingAccount>

#include <KDebug>
#include <KUser>
#include <KLocalizedString>

#include <QFrame>

#include "salut-details-dialog.h"
#include "salut-message-widget.h"

#define TP_PROP_ACCOUNT_ENABLED (QLatin1String("org.freedesktop.Telepathy.Account.Enabled"))
#define TP_PROP_ACCOUNT_SERVICE (QLatin1String("org.freedesktop.Telepathy.Account.Service"))

class SalutEnabler::Private
{
public:
    Private(SalutEnabler* parent)
        : q(parent),
          detailsDialog(0),
          messageWidget(0)
    {
    }

    SalutEnabler *q;

    Tp::ConnectionManagerPtr connectionManager;
    Tp::ProfileManagerPtr profileManager;
    Tp::AccountManagerPtr accountManager;
    Tp::ProfilePtr profile;
    QVariantMap values;
    SalutDetailsDialog *detailsDialog;
    SalutMessageWidget *messageWidget;
    QWeakPointer<QFrame> salutMessageFrame;
};

SalutEnabler::SalutEnabler(const Tp::AccountManagerPtr accountManager, QObject *parent)
    : QObject(parent),
      d(new Private(this))
{
    d->accountManager = accountManager;

    d->connectionManager = Tp::ConnectionManager::create("salut");
    connect(d->connectionManager->becomeReady(),
            SIGNAL(finished(Tp::PendingOperation*)),
            SLOT(onConnectionManagerReady(Tp::PendingOperation*)));
}

SalutEnabler::~SalutEnabler()
{
    delete d;
}

void SalutEnabler::onConnectionManagerReady(Tp::PendingOperation* op)
{
    if(op->isError()) {
        kWarning() << "Creating ConnectionManager failed:" << op->errorName() << op->errorMessage();
    }

    if(!d->connectionManager->isValid()) {
        kWarning() << "Invalid ConnectionManager";
    }

    d->profileManager = Tp::ProfileManager::create(QDBusConnection::sessionBus());

    // FIXME: Until all distros ship correct profile files, we should fake them
    connect(d->profileManager->becomeReady(Tp::Features() << Tp::ProfileManager::FeatureFakeProfiles),
            SIGNAL(finished(Tp::PendingOperation*)),
            SLOT(onProfileManagerReady(Tp::PendingOperation*)));
}

void SalutEnabler::onProfileManagerReady(Tp::PendingOperation* op)
{
    if(op->isError()) {
        kWarning() << "Creating ProfileManager failed:" << op->errorName() << op->errorMessage();
    }

    // Get the protocol's parameters and values.
    Tp::ProtocolInfo protocolInfo = d->connectionManager->protocol(QLatin1String("local-xmpp"));
    Tp::ProtocolParameterList parameters = protocolInfo.parameters();

    d->profile = d->profileManager->profilesForCM("salut").first();

    Q_ASSERT(!d->profile.isNull());
    Q_ASSERT(d->profile->isValid());
    Q_ASSERT(d->profile->protocolName() == QLatin1String("local-xmpp"));
    if (d->profile.isNull() || !d->profile->isValid() || d->profile->protocolName() != QLatin1String("local-xmpp")) {
        kWarning() << "Something went wrong with telepathy salut";
    }

    KUser user = KUser();
    QString name = user.property(KUser::FullName).toString();
    QString nick = user.loginName();
    int lastSpacePosition = name.lastIndexOf(QLatin1Char(' '));
    QString lastname = name.mid(lastSpacePosition + 1);
    QString firstName = name.left(lastSpacePosition);

    d->values.insert("first-name", firstName);
    d->values.insert("last-name", lastname);
    d->values.insert("nickname", nick);

    Q_EMIT userInfoReady();
}

QFrame* SalutEnabler::frameWidget(QWidget* parent)
{
    if (d->salutMessageFrame.isNull()) {
        d->salutMessageFrame = new QFrame(parent);
    }
    d->salutMessageFrame.data()->setMinimumWidth(parent->width());
    d->salutMessageFrame.data()->setFrameShape(QFrame::StyledPanel);

    d->messageWidget = new SalutMessageWidget(d->salutMessageFrame.data());
    d->messageWidget->setParams(d->values["first-name"].toString(), d->values["last-name"].toString(), d->values["nickname"].toString());
    d->messageWidget->hide();

    QPropertyAnimation *animation = new QPropertyAnimation(d->salutMessageFrame.data(), "minimumHeight", d->messageWidget);
    animation->setDuration(150);
    animation->setStartValue(0);
    animation->setEndValue(d->messageWidget->sizeHint().height());
    animation->start();

    connect(animation, SIGNAL(finished()),
            d->messageWidget, SLOT(animatedShow()));

    connect(d->messageWidget, SIGNAL(timeout()),
            this, SLOT(onUserAccepted()));

    connect(d->messageWidget, SIGNAL(configPressed()),
            this, SLOT(onUserWantingChanges()));

    connect(d->messageWidget, SIGNAL(cancelPressed()),
            this, SLOT(onUserCancelled()));

    return d->salutMessageFrame.data();
}

void SalutEnabler::onUserAccepted()
{
    // FIXME: In some next version of tp-qt4 there should be a convenience class for this
    // https://bugs.freedesktop.org/show_bug.cgi?id=33153
    QVariantMap properties;

    if (d->accountManager->supportedAccountProperties().contains(TP_PROP_ACCOUNT_SERVICE)) {
        properties.insert(TP_PROP_ACCOUNT_SERVICE, d->profile->serviceName());
    }
    if (d->accountManager->supportedAccountProperties().contains(TP_PROP_ACCOUNT_ENABLED)) {
        properties.insert(TP_PROP_ACCOUNT_ENABLED, true);
    }

    // FIXME: Ask the user to submit a Display Name

    QString displayName;

    QString lastname = d->values["last-name"].toString();
    QString firstname = d->values["first-name"].toString();
    QString nick = d->values["nickname"].toString();

    //either one of the names is filled and nick is filled
    if (((lastname.isEmpty() && !firstname.isEmpty()) || (!lastname.isEmpty() && firstname.isEmpty()))
            && !nick.isEmpty()) {

        displayName = QString("%1 (%2)").arg(d->values["first-name"].toString().isEmpty() ?
                                                 d->values["last-name"].toString() : d->values["first-name"].toString(),
                                             d->values["nickname"].toString());

    //either one of the names is filled and nick is empty
    } else if (((lastname.isEmpty() && !firstname.isEmpty()) || (!lastname.isEmpty() && firstname.isEmpty()))
            && nick.isEmpty()) {

        displayName = d->values["first-name"].toString().isEmpty() ?
                          d->values["last-name"].toString() : d->values["first-name"].toString();

    //both first & last names are empty but nick is not
    } else if (lastname.isEmpty() && firstname.isEmpty() && !nick.isEmpty()) {

        displayName = d->values["nickname"].toString();

    } else if (lastname.isEmpty() && firstname.isEmpty() && nick.isEmpty()) {
        //FIXME: let the user know that he reached a very strange situation

    } else {
        displayName = QString("%1 %2 (%3)").arg(d->values["first-name"].toString(),
                                                d->values["last-name"].toString(),
                                                d->values["nickname"].toString());
    }

    Tp::PendingAccount *pa = d->accountManager->createAccount(d->profile->cmName(),
                                                              d->profile->protocolName(),
                                                              displayName,
                                                              d->values,
                                                              properties);

    connect(pa,
            SIGNAL(finished(Tp::PendingOperation*)),
            SLOT(onAccountCreated(Tp::PendingOperation*)));
}

void SalutEnabler::onAccountCreated(Tp::PendingOperation* op)
{
    kWarning() << "Account created";
    if(op->isError()) {
        kWarning() << "Creating Account failed:" << op->errorName() << op->errorMessage();
    }

    if (op->isError()) {
        Q_EMIT feedbackMessage(i18n("Failed to create account"),
                               i18n("Possibly not all required fields are valid"),
                               KMessageWidget::Error);
        kWarning() << "Adding Account failed:" << op->errorName() << op->errorMessage();
        return;
    }

    // Get the PendingAccount.
    Tp::PendingAccount *pendingAccount = qobject_cast<Tp::PendingAccount*>(op);
    if (!pendingAccount) {
                Q_EMIT feedbackMessage(i18n("Something went wrong with Telepathy"),
                                       QString(),
                                       KMessageWidget::Error);
        kWarning() << "Method called with wrong type.";
        return;
    }

    pendingAccount->account()->setRequestedPresence(Tp::Presence::available());
    pendingAccount->account()->setServiceName(d->profile->serviceName());

    d->salutMessageFrame.data()->deleteLater();;

    Q_EMIT done();
}

void SalutEnabler::onUserWantingChanges()
{
    d->detailsDialog = new SalutDetailsDialog(d->profileManager, d->connectionManager, 0);

    connect(d->detailsDialog, SIGNAL(dialogAccepted(QVariantMap)),
            this, SLOT(onDialogAccepted(QVariantMap)));

    connect(d->detailsDialog, SIGNAL(rejected()),
            this, SLOT(onUserCancelled()));

    connect(d->detailsDialog, SIGNAL(rejected()),
            this, SIGNAL(cancelled()));

    connect(d->detailsDialog, SIGNAL(feedbackMessage(QString,QString,KMessageWidget::MessageType)),
            this, SIGNAL(feedbackMessage(QString,QString,KMessageWidget::MessageType)));

    d->detailsDialog->exec();
}

void SalutEnabler::onDialogAccepted(const QVariantMap &values)
{
    kDebug() << values;
    d->values.insert("first-name", values["first-name"].toString());
    d->values.insert("last-name", values["last-name"].toString());
    d->values.insert("nickname", values["nickname"].toString());

    onUserAccepted();
}

void SalutEnabler::onUserCancelled()
{
    d->messageWidget->animatedHide();

    QPropertyAnimation *animation = new QPropertyAnimation(d->salutMessageFrame.data(), "maximumHeight", d->messageWidget);
    animation->setDuration(150);
    animation->setStartValue(d->messageWidget->sizeHint().height());
    animation->setEndValue(0);

    QTimer::singleShot(300, animation, SLOT(start()));

    connect(animation, SIGNAL(finished()),
            d->salutMessageFrame.data(), SLOT(deleteLater()));

    connect(animation, SIGNAL(finished()),
            this, SIGNAL(cancelled()));
}
<commit_msg>Make strings const<commit_after>/*
    Class that auto configures link-local xmpp account
    Copyright (C) 2011  Martin Klapetek <martin.klapetek@gmail.com>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "salut-enabler.h"

#include <TelepathyQt/ConnectionManager>
#include <TelepathyQt/ProfileManager>
#include <TelepathyQt/AccountManager>
#include <TelepathyQt/PendingOperation>
#include <TelepathyQt/PendingReady>
#include <TelepathyQt/PendingAccount>

#include <KDebug>
#include <KUser>
#include <KLocalizedString>

#include <QFrame>

#include "salut-details-dialog.h"
#include "salut-message-widget.h"

#define TP_PROP_ACCOUNT_ENABLED (QLatin1String("org.freedesktop.Telepathy.Account.Enabled"))
#define TP_PROP_ACCOUNT_SERVICE (QLatin1String("org.freedesktop.Telepathy.Account.Service"))

const QLatin1String salutConnManager("salut");
const QLatin1String localXmppProtocol("local-xmpp");
const QLatin1String firstNamePar("first-name");
const QLatin1String lastNamePar("last-name");
const QLatin1String nickNamePar("nickname");

class SalutEnabler::Private
{
public:
    Private(SalutEnabler* parent)
        : q(parent),
          detailsDialog(0),
          messageWidget(0)
    {
    }

    SalutEnabler *q;

    Tp::ConnectionManagerPtr connectionManager;
    Tp::ProfileManagerPtr profileManager;
    Tp::AccountManagerPtr accountManager;
    Tp::ProfilePtr profile;
    QVariantMap values;
    SalutDetailsDialog *detailsDialog;
    SalutMessageWidget *messageWidget;
    QWeakPointer<QFrame> salutMessageFrame;
};

SalutEnabler::SalutEnabler(const Tp::AccountManagerPtr accountManager, QObject *parent)
    : QObject(parent),
      d(new Private(this))
{
    d->accountManager = accountManager;

    d->connectionManager = Tp::ConnectionManager::create(salutConnManager);
    connect(d->connectionManager->becomeReady(),
            SIGNAL(finished(Tp::PendingOperation*)),
            SLOT(onConnectionManagerReady(Tp::PendingOperation*)));
}

SalutEnabler::~SalutEnabler()
{
    delete d;
}

void SalutEnabler::onConnectionManagerReady(Tp::PendingOperation* op)
{
    if(op->isError()) {
        kWarning() << "Creating ConnectionManager failed:" << op->errorName() << op->errorMessage();
    }

    if(!d->connectionManager->isValid()) {
        kWarning() << "Invalid ConnectionManager";
    }

    d->profileManager = Tp::ProfileManager::create(QDBusConnection::sessionBus());

    // FIXME: Until all distros ship correct profile files, we should fake them
    connect(d->profileManager->becomeReady(Tp::Features() << Tp::ProfileManager::FeatureFakeProfiles),
            SIGNAL(finished(Tp::PendingOperation*)),
            SLOT(onProfileManagerReady(Tp::PendingOperation*)));
}

void SalutEnabler::onProfileManagerReady(Tp::PendingOperation* op)
{
    if(op->isError()) {
        kWarning() << "Creating ProfileManager failed:" << op->errorName() << op->errorMessage();
    }

    // Get the protocol's parameters and values.
    Tp::ProtocolInfo protocolInfo = d->connectionManager->protocol(localXmppProtocol);
    Tp::ProtocolParameterList parameters = protocolInfo.parameters();

    d->profile = d->profileManager->profilesForCM(salutConnManager).first();

    Q_ASSERT(!d->profile.isNull());
    Q_ASSERT(d->profile->isValid());
    Q_ASSERT(d->profile->protocolName() == localXmppProtocol);
    if (d->profile.isNull() || !d->profile->isValid() || d->profile->protocolName() != localXmppProtocol) {
        kWarning() << "Something went wrong with telepathy salut";
    }

    KUser user = KUser();
    QString name = user.property(KUser::FullName).toString();
    QString nick = user.loginName();
    int lastSpacePosition = name.lastIndexOf(QLatin1Char(' '));
    QString lastname = name.mid(lastSpacePosition + 1);
    QString firstName = name.left(lastSpacePosition);

    d->values.insert(firstNamePar, firstName);
    d->values.insert(lastNamePar, lastname);
    d->values.insert(nickNamePar, nick);

    Q_EMIT userInfoReady();
}

QFrame* SalutEnabler::frameWidget(QWidget* parent)
{
    if (d->salutMessageFrame.isNull()) {
        d->salutMessageFrame = new QFrame(parent);
    }
    d->salutMessageFrame.data()->setMinimumWidth(parent->width());
    d->salutMessageFrame.data()->setFrameShape(QFrame::StyledPanel);

    d->messageWidget = new SalutMessageWidget(d->salutMessageFrame.data());
    d->messageWidget->setParams(d->values[firstNamePar].toString(),
                                d->values[lastNamePar].toString(),
                                d->values[nickNamePar].toString());
    d->messageWidget->hide();

    QPropertyAnimation *animation = new QPropertyAnimation(d->salutMessageFrame.data(), "minimumHeight", d->messageWidget);
    animation->setDuration(150);
    animation->setStartValue(0);
    animation->setEndValue(d->messageWidget->sizeHint().height());
    animation->start();

    connect(animation, SIGNAL(finished()),
            d->messageWidget, SLOT(animatedShow()));

    connect(d->messageWidget, SIGNAL(timeout()),
            this, SLOT(onUserAccepted()));

    connect(d->messageWidget, SIGNAL(configPressed()),
            this, SLOT(onUserWantingChanges()));

    connect(d->messageWidget, SIGNAL(cancelPressed()),
            this, SLOT(onUserCancelled()));

    return d->salutMessageFrame.data();
}

void SalutEnabler::onUserAccepted()
{
    // FIXME: In some next version of tp-qt4 there should be a convenience class for this
    // https://bugs.freedesktop.org/show_bug.cgi?id=33153
    QVariantMap properties;

    if (d->accountManager->supportedAccountProperties().contains(TP_PROP_ACCOUNT_SERVICE)) {
        properties.insert(TP_PROP_ACCOUNT_SERVICE, d->profile->serviceName());
    }
    if (d->accountManager->supportedAccountProperties().contains(TP_PROP_ACCOUNT_ENABLED)) {
        properties.insert(TP_PROP_ACCOUNT_ENABLED, true);
    }

    // FIXME: Ask the user to submit a Display Name

    QString displayName;

    QString lastname = d->values[lastNamePar].toString();
    QString firstname = d->values[firstNamePar].toString();
    QString nick = d->values[nickNamePar].toString();

    //either one of the names is filled and nick is filled
    if (((lastname.isEmpty() && !firstname.isEmpty()) || (!lastname.isEmpty() && firstname.isEmpty()))
            && !nick.isEmpty()) {

        displayName = QString(QLatin1String("%1 (%2)")).arg(d->values[firstNamePar].toString().isEmpty() ?
                d->values[lastNamePar].toString() : d->values[firstNamePar].toString(),
                                                            d->values[nickNamePar].toString());

    //either one of the names is filled and nick is empty
    } else if (((lastname.isEmpty() && !firstname.isEmpty()) || (!lastname.isEmpty() && firstname.isEmpty()))
            && nick.isEmpty()) {

        displayName = d->values[firstNamePar].toString().isEmpty() ?
                d->values[lastNamePar].toString() : d->values[firstNamePar].toString();

    //both first & last names are empty but nick is not
    } else if (lastname.isEmpty() && firstname.isEmpty() && !nick.isEmpty()) {

        displayName = d->values[nickNamePar].toString();

    } else if (lastname.isEmpty() && firstname.isEmpty() && nick.isEmpty()) {
        //FIXME: let the user know that he reached a very strange situation

    } else {
        displayName = QString(QLatin1String("%1 %2 (%3)")).arg(d->values[firstNamePar].toString(),
                                                               d->values[lastNamePar].toString(),
                                                               d->values[nickNamePar].toString());
    }

    Tp::PendingAccount *pa = d->accountManager->createAccount(d->profile->cmName(),
                                                              d->profile->protocolName(),
                                                              displayName,
                                                              d->values,
                                                              properties);

    connect(pa,
            SIGNAL(finished(Tp::PendingOperation*)),
            SLOT(onAccountCreated(Tp::PendingOperation*)));
}

void SalutEnabler::onAccountCreated(Tp::PendingOperation* op)
{
    kWarning() << "Account created";
    if(op->isError()) {
        kWarning() << "Creating Account failed:" << op->errorName() << op->errorMessage();
    }

    if (op->isError()) {
        Q_EMIT feedbackMessage(i18n("Failed to create account"),
                               i18n("Possibly not all required fields are valid"),
                               KMessageWidget::Error);
        kWarning() << "Adding Account failed:" << op->errorName() << op->errorMessage();
        return;
    }

    // Get the PendingAccount.
    Tp::PendingAccount *pendingAccount = qobject_cast<Tp::PendingAccount*>(op);
    if (!pendingAccount) {
                Q_EMIT feedbackMessage(i18n("Something went wrong with Telepathy"),
                                       QString(),
                                       KMessageWidget::Error);
        kWarning() << "Method called with wrong type.";
        return;
    }

    pendingAccount->account()->setRequestedPresence(Tp::Presence::available());
    pendingAccount->account()->setServiceName(d->profile->serviceName());

    d->salutMessageFrame.data()->deleteLater();;

    Q_EMIT done();
}

void SalutEnabler::onUserWantingChanges()
{
    d->detailsDialog = new SalutDetailsDialog(d->profileManager, d->connectionManager, 0);

    connect(d->detailsDialog, SIGNAL(dialogAccepted(QVariantMap)),
            this, SLOT(onDialogAccepted(QVariantMap)));

    connect(d->detailsDialog, SIGNAL(rejected()),
            this, SLOT(onUserCancelled()));

    connect(d->detailsDialog, SIGNAL(rejected()),
            this, SIGNAL(cancelled()));

    connect(d->detailsDialog, SIGNAL(feedbackMessage(QString,QString,KMessageWidget::MessageType)),
            this, SIGNAL(feedbackMessage(QString,QString,KMessageWidget::MessageType)));

    d->detailsDialog->exec();
}

void SalutEnabler::onDialogAccepted(const QVariantMap &values)
{
    kDebug() << values;
    d->values.insert(firstNamePar, values[firstNamePar].toString());
    d->values.insert(lastNamePar, values[lastNamePar].toString());
    d->values.insert(nickNamePar, values[nickNamePar].toString());

    onUserAccepted();
}

void SalutEnabler::onUserCancelled()
{
    d->messageWidget->animatedHide();

    QPropertyAnimation *animation = new QPropertyAnimation(d->salutMessageFrame.data(), "maximumHeight", d->messageWidget);
    animation->setDuration(150);
    animation->setStartValue(d->messageWidget->sizeHint().height());
    animation->setEndValue(0);

    QTimer::singleShot(300, animation, SLOT(start()));

    connect(animation, SIGNAL(finished()),
            d->salutMessageFrame.data(), SLOT(deleteLater()));

    connect(animation, SIGNAL(finished()),
            this, SIGNAL(cancelled()));
}
<|endoftext|>