<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 "ash/system/ime/tray_ime_chromeos.h"

#include <vector>

#include "ash/metrics/user_metrics_recorder.h"
#include "ash/root_window_controller.h"
#include "ash/session/session_state_delegate.h"
#include "ash/shelf/shelf_widget.h"
#include "ash/shell.h"
#include "ash/system/tray/hover_highlight_view.h"
#include "ash/system/tray/system_tray.h"
#include "ash/system/tray/system_tray_delegate.h"
#include "ash/system/tray/system_tray_notifier.h"
#include "ash/system/tray/tray_constants.h"
#include "ash/system/tray/tray_details_view.h"
#include "ash/system/tray/tray_item_more.h"
#include "ash/system/tray/tray_item_view.h"
#include "ash/system/tray/tray_utils.h"
#include "ash/system/tray_accessibility.h"
#include "ash/virtual_keyboard_controller.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "grit/ash_resources.h"
#include "grit/ash_strings.h"
#include "ui/accessibility/ax_enums.h"
#include "ui/accessibility/ax_view_state.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/font.h"
#include "ui/gfx/image/image.h"
#include "ui/keyboard/keyboard_util.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/widget/widget.h"

namespace ash {
namespace tray {

// A |HoverHighlightView| that uses bold or normal font depending on whether
// it is selected.  This view exposes itself as a checkbox to the accessibility
// framework.
class SelectableHoverHighlightView : public HoverHighlightView {
 public:
  SelectableHoverHighlightView(ViewClickListener* listener,
                               const base::string16& label,
                               bool selected)
      : HoverHighlightView(listener), selected_(selected) {
    AddLabel(label, gfx::ALIGN_LEFT, selected);
  }

  ~SelectableHoverHighlightView() override {}

 protected:
  // Overridden from views::View.
  void GetAccessibleState(ui::AXViewState* state) override {
    HoverHighlightView::GetAccessibleState(state);
    state->role = ui::AX_ROLE_CHECK_BOX;
    if (selected_)
      state->AddStateFlag(ui::AX_STATE_CHECKED);
  }

 private:
  bool selected_;

  DISALLOW_COPY_AND_ASSIGN(SelectableHoverHighlightView);
};

class IMEDefaultView : public TrayItemMore {
 public:
  explicit IMEDefaultView(SystemTrayItem* owner, const base::string16& label)
      : TrayItemMore(owner, true) {
    ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
    SetImage(bundle.GetImageNamed(IDR_AURA_UBER_TRAY_IME).ToImageSkia());
    UpdateLabel(label);
  }

  ~IMEDefaultView() override {}

  void UpdateLabel(const base::string16& label) {
    SetLabel(label);
    SetAccessibleName(label);
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(IMEDefaultView);
};

class IMEDetailedView : public TrayDetailsView, public ViewClickListener {
 public:
  IMEDetailedView(SystemTrayItem* owner,
                  user::LoginStatus login,
                  bool show_keyboard_toggle)
      : TrayDetailsView(owner), login_(login) {
    SystemTrayDelegate* delegate = Shell::GetInstance()->system_tray_delegate();
    IMEInfoList list;
    delegate->GetAvailableIMEList(&list);
    IMEPropertyInfoList property_list;
    delegate->GetCurrentIMEProperties(&property_list);
    Update(list, property_list, show_keyboard_toggle);
  }

  ~IMEDetailedView() override {}

  void Update(const IMEInfoList& list,
              const IMEPropertyInfoList& property_list,
              bool show_keyboard_toggle) {
    Reset();
    ime_map_.clear();
    property_map_.clear();
    CreateScrollableList();

    if (list.size() > 1)
      AppendIMEList(list);
    if (property_list.size() > 1)
      AppendIMEProperties(property_list);

    if (show_keyboard_toggle) {
      if (list.size() > 1 || property_list.size() > 1)
        AddScrollSeparator();
      AppendKeyboardStatus();
    }

    bool userAddingRunning = ash::Shell::GetInstance()
                                 ->session_state_delegate()
                                 ->IsInSecondaryLoginScreen();
    if (login_ != user::LOGGED_IN_NONE && login_ != user::LOGGED_IN_LOCKED &&
        !userAddingRunning)
      AppendSettings();
    AppendHeaderEntry();

    Layout();
    SchedulePaint();
  }

 private:
  void AppendHeaderEntry() { CreateSpecialRow(IDS_ASH_STATUS_TRAY_IME, this); }

  // Appends the IMEs to the scrollable area of the detailed view.
  void AppendIMEList(const IMEInfoList& list) {
    DCHECK(ime_map_.empty());
    for (size_t i = 0; i < list.size(); i++) {
      HoverHighlightView* container = new SelectableHoverHighlightView(
          this, list[i].name, list[i].selected);
      scroll_content()->AddChildView(container);
      ime_map_[container] = list[i].id;
    }
  }

  // Appends the IME listed to the scrollable area of the detailed
  // view.
  void AppendIMEProperties(const IMEPropertyInfoList& property_list) {
    DCHECK(property_map_.empty());
    for (size_t i = 0; i < property_list.size(); i++) {
      HoverHighlightView* container = new SelectableHoverHighlightView(
          this, property_list[i].name, property_list[i].selected);
      if (i == 0)
        container->SetBorder(views::Border::CreateSolidSidedBorder(
            1, 0, 0, 0, kBorderLightColor));
      scroll_content()->AddChildView(container);
      property_map_[container] = property_list[i].key;
    }
  }

  void AppendKeyboardStatus() {
    HoverHighlightView* container = new HoverHighlightView(this);
    int id = keyboard::IsKeyboardEnabled()
                 ? IDS_ASH_STATUS_TRAY_DISABLE_KEYBOARD
                 : IDS_ASH_STATUS_TRAY_ENABLE_KEYBOARD;
    container->AddLabel(
        ui::ResourceBundle::GetSharedInstance().GetLocalizedString(id),
        gfx::ALIGN_LEFT, false /* highlight */);
    scroll_content()->AddChildView(container);
    keyboard_status_ = container;
  }

  void AppendSettings() {
    HoverHighlightView* container = new HoverHighlightView(this);
    container->AddLabel(
        ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
            IDS_ASH_STATUS_TRAY_IME_SETTINGS),
        gfx::ALIGN_LEFT, false /* highlight */);
    AddChildView(container);
    settings_ = container;
  }

  // Overridden from ViewClickListener.
  void OnViewClicked(views::View* sender) override {
    SystemTrayDelegate* delegate = Shell::GetInstance()->system_tray_delegate();
    if (sender == footer()->content()) {
      TransitionToDefaultView();
    } else if (sender == settings_) {
      Shell::GetInstance()->metrics()->RecordUserMetricsAction(
          ash::UMA_STATUS_AREA_IME_SHOW_DETAILED);
      delegate->ShowIMESettings();
    } else if (sender == keyboard_status_) {
      Shell::GetInstance()->virtual_keyboard_controller()
          ->ToggleIgnoreExternalKeyboard();
    } else {
      std::map<views::View*, std::string>::const_iterator ime_find;
      ime_find = ime_map_.find(sender);
      if (ime_find != ime_map_.end()) {
        Shell::GetInstance()->metrics()->RecordUserMetricsAction(
            ash::UMA_STATUS_AREA_IME_SWITCH_MODE);
        std::string ime_id = ime_find->second;
        delegate->SwitchIME(ime_id);
        GetWidget()->Close();
      } else {
        std::map<views::View*, std::string>::const_iterator prop_find;
        prop_find = property_map_.find(sender);
        if (prop_find != property_map_.end()) {
          const std::string key = prop_find->second;
          delegate->ActivateIMEProperty(key);
          GetWidget()->Close();
        }
      }
    }
  }

  user::LoginStatus login_;

  std::map<views::View*, std::string> ime_map_;
  std::map<views::View*, std::string> property_map_;
  views::View* settings_;
  views::View* keyboard_status_;

  DISALLOW_COPY_AND_ASSIGN(IMEDetailedView);
};

}  // namespace tray

TrayIME::TrayIME(SystemTray* system_tray)
    : SystemTrayItem(system_tray),
      tray_label_(NULL),
      default_(NULL),
      detailed_(NULL),
      keyboard_suppressed_(false) {
  Shell::GetInstance()->system_tray_notifier()->AddIMEObserver(this);
  Shell::GetInstance()->system_tray_notifier()->AddVirtualKeyboardObserver(
      this);
  Shell::GetInstance()->system_tray_notifier()->AddAccessibilityObserver(this);
}

TrayIME::~TrayIME() {
  Shell::GetInstance()->system_tray_notifier()->RemoveIMEObserver(this);
  Shell::GetInstance()->system_tray_notifier()->RemoveAccessibilityObserver(
      this);
  Shell::GetInstance()->system_tray_notifier()->RemoveVirtualKeyboardObserver(
      this);
}

void TrayIME::OnKeyboardSuppressionChanged(bool suppressed) {
  keyboard_suppressed_ = suppressed;
  Update();
}

void TrayIME::OnAccessibilityModeChanged(
    ui::AccessibilityNotificationVisibility notify) {
  Update();
}

void TrayIME::Update() {
  UpdateTrayLabel(current_ime_, ime_list_.size());
  if (default_) {
    default_->SetVisible(ShouldDefaultViewBeVisible());
    default_->UpdateLabel(GetDefaultViewLabel(ime_list_.size() > 1));
  }
  if (detailed_)
    detailed_->Update(ime_list_, property_list_, ShouldShowKeyboardToggle());
}

void TrayIME::UpdateTrayLabel(const IMEInfo& current, size_t count) {
  if (tray_label_) {
    bool visible = count > 1;
    tray_label_->SetVisible(visible);
    // Do not change label before hiding because this change is noticeable.
    if (!visible)
      return;
    if (current.third_party) {
      tray_label_->label()->SetText(current.short_name +
                                    base::UTF8ToUTF16("*"));
    } else {
      tray_label_->label()->SetText(current.short_name);
    }
    SetTrayLabelItemBorder(tray_label_, system_tray()->shelf_alignment());
    tray_label_->Layout();
  }
}

bool TrayIME::ShouldShowKeyboardToggle() {
  return keyboard_suppressed_ &&
         !Shell::GetInstance()
              ->accessibility_delegate()
              ->IsVirtualKeyboardEnabled();
}

base::string16 TrayIME::GetDefaultViewLabel(bool show_ime_label) {
  if (show_ime_label) {
    IMEInfo current;
    Shell::GetInstance()->system_tray_delegate()->GetCurrentIME(&current);
    return current.name;
  } else {
    // Display virtual keyboard status instead.
    int id = keyboard::IsKeyboardEnabled()
                 ? IDS_ASH_STATUS_TRAY_KEYBOARD_ENABLED
                 : IDS_ASH_STATUS_TRAY_KEYBOARD_DISABLED;
    return ui::ResourceBundle::GetSharedInstance().GetLocalizedString(id);
  }
}

views::View* TrayIME::CreateTrayView(user::LoginStatus status) {
  CHECK(tray_label_ == NULL);
  tray_label_ = new TrayItemView(this);
  tray_label_->CreateLabel();
  SetupLabelForTray(tray_label_->label());
  // Hide IME tray when it is created, it will be updated when it is notified
  // of the IME refresh event.
  tray_label_->SetVisible(false);
  return tray_label_;
}

views::View* TrayIME::CreateDefaultView(user::LoginStatus status) {
  CHECK(default_ == NULL);
  default_ =
      new tray::IMEDefaultView(this, GetDefaultViewLabel(ime_list_.size() > 1));
  default_->SetVisible(ShouldDefaultViewBeVisible());
  return default_;
}

views::View* TrayIME::CreateDetailedView(user::LoginStatus status) {
  CHECK(detailed_ == NULL);
  detailed_ =
      new tray::IMEDetailedView(this, status, ShouldShowKeyboardToggle());
  return detailed_;
}

void TrayIME::DestroyTrayView() {
  tray_label_ = NULL;
}

void TrayIME::DestroyDefaultView() {
  default_ = NULL;
}

void TrayIME::DestroyDetailedView() {
  detailed_ = NULL;
}

void TrayIME::UpdateAfterLoginStatusChange(user::LoginStatus status) {
}

void TrayIME::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) {
  SetTrayLabelItemBorder(tray_label_, alignment);
  tray_label_->Layout();
}

void TrayIME::OnIMERefresh() {
  // Caches the current ime state.
  SystemTrayDelegate* delegate = Shell::GetInstance()->system_tray_delegate();
  ime_list_.clear();
  property_list_.clear();
  delegate->GetCurrentIME(&current_ime_);
  delegate->GetAvailableIMEList(&ime_list_);
  delegate->GetCurrentIMEProperties(&property_list_);

  Update();
}

bool TrayIME::ShouldDefaultViewBeVisible() {
  return ime_list_.size() > 1 || property_list_.size() > 1 ||
         ShouldShowKeyboardToggle();
}

}  // namespace ash
<commit_msg>Fix IME menu not showing if menu has only one item.<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 "ash/system/ime/tray_ime_chromeos.h"

#include <vector>

#include "ash/metrics/user_metrics_recorder.h"
#include "ash/root_window_controller.h"
#include "ash/session/session_state_delegate.h"
#include "ash/shelf/shelf_widget.h"
#include "ash/shell.h"
#include "ash/system/tray/hover_highlight_view.h"
#include "ash/system/tray/system_tray.h"
#include "ash/system/tray/system_tray_delegate.h"
#include "ash/system/tray/system_tray_notifier.h"
#include "ash/system/tray/tray_constants.h"
#include "ash/system/tray/tray_details_view.h"
#include "ash/system/tray/tray_item_more.h"
#include "ash/system/tray/tray_item_view.h"
#include "ash/system/tray/tray_utils.h"
#include "ash/system/tray_accessibility.h"
#include "ash/virtual_keyboard_controller.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "grit/ash_resources.h"
#include "grit/ash_strings.h"
#include "ui/accessibility/ax_enums.h"
#include "ui/accessibility/ax_view_state.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/font.h"
#include "ui/gfx/image/image.h"
#include "ui/keyboard/keyboard_util.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/widget/widget.h"

namespace ash {
namespace tray {

// A |HoverHighlightView| that uses bold or normal font depending on whether
// it is selected.  This view exposes itself as a checkbox to the accessibility
// framework.
class SelectableHoverHighlightView : public HoverHighlightView {
 public:
  SelectableHoverHighlightView(ViewClickListener* listener,
                               const base::string16& label,
                               bool selected)
      : HoverHighlightView(listener), selected_(selected) {
    AddLabel(label, gfx::ALIGN_LEFT, selected);
  }

  ~SelectableHoverHighlightView() override {}

 protected:
  // Overridden from views::View.
  void GetAccessibleState(ui::AXViewState* state) override {
    HoverHighlightView::GetAccessibleState(state);
    state->role = ui::AX_ROLE_CHECK_BOX;
    if (selected_)
      state->AddStateFlag(ui::AX_STATE_CHECKED);
  }

 private:
  bool selected_;

  DISALLOW_COPY_AND_ASSIGN(SelectableHoverHighlightView);
};

class IMEDefaultView : public TrayItemMore {
 public:
  explicit IMEDefaultView(SystemTrayItem* owner, const base::string16& label)
      : TrayItemMore(owner, true) {
    ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
    SetImage(bundle.GetImageNamed(IDR_AURA_UBER_TRAY_IME).ToImageSkia());
    UpdateLabel(label);
  }

  ~IMEDefaultView() override {}

  void UpdateLabel(const base::string16& label) {
    SetLabel(label);
    SetAccessibleName(label);
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(IMEDefaultView);
};

class IMEDetailedView : public TrayDetailsView, public ViewClickListener {
 public:
  IMEDetailedView(SystemTrayItem* owner,
                  user::LoginStatus login,
                  bool show_keyboard_toggle)
      : TrayDetailsView(owner), login_(login) {
    SystemTrayDelegate* delegate = Shell::GetInstance()->system_tray_delegate();
    IMEInfoList list;
    delegate->GetAvailableIMEList(&list);
    IMEPropertyInfoList property_list;
    delegate->GetCurrentIMEProperties(&property_list);
    Update(list, property_list, show_keyboard_toggle);
  }

  ~IMEDetailedView() override {}

  void Update(const IMEInfoList& list,
              const IMEPropertyInfoList& property_list,
              bool show_keyboard_toggle) {
    Reset();
    ime_map_.clear();
    property_map_.clear();
    CreateScrollableList();

    if (list.size() > 1)
      AppendIMEList(list);
    if (!property_list.empty())
      AppendIMEProperties(property_list);

    if (show_keyboard_toggle) {
      if (list.size() > 1 || !property_list.empty())
        AddScrollSeparator();
      AppendKeyboardStatus();
    }

    bool userAddingRunning = ash::Shell::GetInstance()
                                 ->session_state_delegate()
                                 ->IsInSecondaryLoginScreen();
    if (login_ != user::LOGGED_IN_NONE && login_ != user::LOGGED_IN_LOCKED &&
        !userAddingRunning)
      AppendSettings();
    AppendHeaderEntry();

    Layout();
    SchedulePaint();
  }

 private:
  void AppendHeaderEntry() { CreateSpecialRow(IDS_ASH_STATUS_TRAY_IME, this); }

  // Appends the IMEs to the scrollable area of the detailed view.
  void AppendIMEList(const IMEInfoList& list) {
    DCHECK(ime_map_.empty());
    for (size_t i = 0; i < list.size(); i++) {
      HoverHighlightView* container = new SelectableHoverHighlightView(
          this, list[i].name, list[i].selected);
      scroll_content()->AddChildView(container);
      ime_map_[container] = list[i].id;
    }
  }

  // Appends the IME listed to the scrollable area of the detailed
  // view.
  void AppendIMEProperties(const IMEPropertyInfoList& property_list) {
    DCHECK(property_map_.empty());
    for (size_t i = 0; i < property_list.size(); i++) {
      HoverHighlightView* container = new SelectableHoverHighlightView(
          this, property_list[i].name, property_list[i].selected);
      if (i == 0)
        container->SetBorder(views::Border::CreateSolidSidedBorder(
            1, 0, 0, 0, kBorderLightColor));
      scroll_content()->AddChildView(container);
      property_map_[container] = property_list[i].key;
    }
  }

  void AppendKeyboardStatus() {
    HoverHighlightView* container = new HoverHighlightView(this);
    int id = keyboard::IsKeyboardEnabled()
                 ? IDS_ASH_STATUS_TRAY_DISABLE_KEYBOARD
                 : IDS_ASH_STATUS_TRAY_ENABLE_KEYBOARD;
    container->AddLabel(
        ui::ResourceBundle::GetSharedInstance().GetLocalizedString(id),
        gfx::ALIGN_LEFT, false /* highlight */);
    scroll_content()->AddChildView(container);
    keyboard_status_ = container;
  }

  void AppendSettings() {
    HoverHighlightView* container = new HoverHighlightView(this);
    container->AddLabel(
        ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
            IDS_ASH_STATUS_TRAY_IME_SETTINGS),
        gfx::ALIGN_LEFT, false /* highlight */);
    AddChildView(container);
    settings_ = container;
  }

  // Overridden from ViewClickListener.
  void OnViewClicked(views::View* sender) override {
    SystemTrayDelegate* delegate = Shell::GetInstance()->system_tray_delegate();
    if (sender == footer()->content()) {
      TransitionToDefaultView();
    } else if (sender == settings_) {
      Shell::GetInstance()->metrics()->RecordUserMetricsAction(
          ash::UMA_STATUS_AREA_IME_SHOW_DETAILED);
      delegate->ShowIMESettings();
    } else if (sender == keyboard_status_) {
      Shell::GetInstance()->virtual_keyboard_controller()
          ->ToggleIgnoreExternalKeyboard();
    } else {
      std::map<views::View*, std::string>::const_iterator ime_find;
      ime_find = ime_map_.find(sender);
      if (ime_find != ime_map_.end()) {
        Shell::GetInstance()->metrics()->RecordUserMetricsAction(
            ash::UMA_STATUS_AREA_IME_SWITCH_MODE);
        std::string ime_id = ime_find->second;
        delegate->SwitchIME(ime_id);
        GetWidget()->Close();
      } else {
        std::map<views::View*, std::string>::const_iterator prop_find;
        prop_find = property_map_.find(sender);
        if (prop_find != property_map_.end()) {
          const std::string key = prop_find->second;
          delegate->ActivateIMEProperty(key);
          GetWidget()->Close();
        }
      }
    }
  }

  user::LoginStatus login_;

  std::map<views::View*, std::string> ime_map_;
  std::map<views::View*, std::string> property_map_;
  views::View* settings_;
  views::View* keyboard_status_;

  DISALLOW_COPY_AND_ASSIGN(IMEDetailedView);
};

}  // namespace tray

TrayIME::TrayIME(SystemTray* system_tray)
    : SystemTrayItem(system_tray),
      tray_label_(NULL),
      default_(NULL),
      detailed_(NULL),
      keyboard_suppressed_(false) {
  Shell::GetInstance()->system_tray_notifier()->AddIMEObserver(this);
  Shell::GetInstance()->system_tray_notifier()->AddVirtualKeyboardObserver(
      this);
  Shell::GetInstance()->system_tray_notifier()->AddAccessibilityObserver(this);
}

TrayIME::~TrayIME() {
  Shell::GetInstance()->system_tray_notifier()->RemoveIMEObserver(this);
  Shell::GetInstance()->system_tray_notifier()->RemoveAccessibilityObserver(
      this);
  Shell::GetInstance()->system_tray_notifier()->RemoveVirtualKeyboardObserver(
      this);
}

void TrayIME::OnKeyboardSuppressionChanged(bool suppressed) {
  keyboard_suppressed_ = suppressed;
  Update();
}

void TrayIME::OnAccessibilityModeChanged(
    ui::AccessibilityNotificationVisibility notify) {
  Update();
}

void TrayIME::Update() {
  UpdateTrayLabel(current_ime_, ime_list_.size());
  if (default_) {
    default_->SetVisible(ShouldDefaultViewBeVisible());
    default_->UpdateLabel(GetDefaultViewLabel(ime_list_.size() > 1));
  }
  if (detailed_)
    detailed_->Update(ime_list_, property_list_, ShouldShowKeyboardToggle());
}

void TrayIME::UpdateTrayLabel(const IMEInfo& current, size_t count) {
  if (tray_label_) {
    bool visible = count > 1;
    tray_label_->SetVisible(visible);
    // Do not change label before hiding because this change is noticeable.
    if (!visible)
      return;
    if (current.third_party) {
      tray_label_->label()->SetText(current.short_name +
                                    base::UTF8ToUTF16("*"));
    } else {
      tray_label_->label()->SetText(current.short_name);
    }
    SetTrayLabelItemBorder(tray_label_, system_tray()->shelf_alignment());
    tray_label_->Layout();
  }
}

bool TrayIME::ShouldShowKeyboardToggle() {
  return keyboard_suppressed_ &&
         !Shell::GetInstance()
              ->accessibility_delegate()
              ->IsVirtualKeyboardEnabled();
}

base::string16 TrayIME::GetDefaultViewLabel(bool show_ime_label) {
  if (show_ime_label) {
    IMEInfo current;
    Shell::GetInstance()->system_tray_delegate()->GetCurrentIME(&current);
    return current.name;
  } else {
    // Display virtual keyboard status instead.
    int id = keyboard::IsKeyboardEnabled()
                 ? IDS_ASH_STATUS_TRAY_KEYBOARD_ENABLED
                 : IDS_ASH_STATUS_TRAY_KEYBOARD_DISABLED;
    return ui::ResourceBundle::GetSharedInstance().GetLocalizedString(id);
  }
}

views::View* TrayIME::CreateTrayView(user::LoginStatus status) {
  CHECK(tray_label_ == NULL);
  tray_label_ = new TrayItemView(this);
  tray_label_->CreateLabel();
  SetupLabelForTray(tray_label_->label());
  // Hide IME tray when it is created, it will be updated when it is notified
  // of the IME refresh event.
  tray_label_->SetVisible(false);
  return tray_label_;
}

views::View* TrayIME::CreateDefaultView(user::LoginStatus status) {
  CHECK(default_ == NULL);
  default_ =
      new tray::IMEDefaultView(this, GetDefaultViewLabel(ime_list_.size() > 1));
  default_->SetVisible(ShouldDefaultViewBeVisible());
  return default_;
}

views::View* TrayIME::CreateDetailedView(user::LoginStatus status) {
  CHECK(detailed_ == NULL);
  detailed_ =
      new tray::IMEDetailedView(this, status, ShouldShowKeyboardToggle());
  return detailed_;
}

void TrayIME::DestroyTrayView() {
  tray_label_ = NULL;
}

void TrayIME::DestroyDefaultView() {
  default_ = NULL;
}

void TrayIME::DestroyDetailedView() {
  detailed_ = NULL;
}

void TrayIME::UpdateAfterLoginStatusChange(user::LoginStatus status) {
}

void TrayIME::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) {
  SetTrayLabelItemBorder(tray_label_, alignment);
  tray_label_->Layout();
}

void TrayIME::OnIMERefresh() {
  // Caches the current ime state.
  SystemTrayDelegate* delegate = Shell::GetInstance()->system_tray_delegate();
  ime_list_.clear();
  property_list_.clear();
  delegate->GetCurrentIME(&current_ime_);
  delegate->GetAvailableIMEList(&ime_list_);
  delegate->GetCurrentIMEProperties(&property_list_);

  Update();
}

bool TrayIME::ShouldDefaultViewBeVisible() {
  return ime_list_.size() > 1 || property_list_.size() > 1 ||
         ShouldShowKeyboardToggle();
}

}  // namespace ash
<|endoftext|>


<commit_before><commit_msg>Fixup old file path on Windows<commit_after><|endoftext|>


<commit_before>#include "dungeon_engine.h"
#include "printutils.h"
#include "utils.h"
#include "command_window.h"
#include "string_constants.h"

using namespace std;

string DungeonEngine::exit(string args)
{
	return STR_EXIT;
}

string DungeonEngine::pageUp(string args)
{
	renderOffset = min(renderOffset+25,textBuffer.size());
	return "";
}

string DungeonEngine::pageDown(string args)
{
	renderOffset = max(0,renderOffset - 25);
	return "";
}

string DungeonEngine::drop(string args)
{
	DungeonObject *thing = (DungeonObject*)extractEntity(&player->objects,&args);
	if(thing != nullptr) {
		removeObject(&player->objects,thing);
		room->objects.push_back(thing);
		return "You drop the " + thing->getPrimaryName() +".";
	}
	else {
		return "You don't have that.";
	}
}

string DungeonEngine::examine(string args)
{
	DungeonObject* thing =(DungeonObject*)extractEntity(&room->objects,&args);
	if(thing == nullptr)
	{
		thing = (DungeonObject*)extractEntity(&player->objects,&args);
	}

	if(thing != nullptr && thing->description.size() == 0)
	{
		return "You see no further detail.";

	}
	else if(thing != nullptr)
	{
		addToBuffer(&thing->description);
		return "";
	}
	else {
		DungeonCreature *gal = (DungeonCreature*)extractEntity(&room->creatures,&args);
		if(gal != nullptr)
		{
			if(gal->description.size() == 0)
			{
				return "There is nothing more to see.";
			}
			else {
				addToBuffer(&gal->description);
				return "";
			}
		}
		else
		{
			return "You don't see that here.";
		}
	}

	return "investigate examine function more";
}

string DungeonEngine::put(string args)
{
	//get the string before and after the word "in" to clarify what is being put where
	unsigned long inLocation = args.find(" in ");
	if(inLocation == string::npos)
	{
		return "Your fumble about, but it doesn't work.";
	}

	string firstHalf = args.substr(0,inLocation);
	string secondHalf = args.substr(inLocation+4,args.size()-(inLocation+4));

	DungeonObject* containerObject =  (DungeonObject*)extractEntity(&player->objects,&secondHalf);
	if(containerObject == nullptr)
	{
		containerObject = (DungeonObject*)extractEntity(&room->objects,&secondHalf);
	}

	if(containerObject != nullptr && containerObject->isOpen)
	{
		DungeonObject* putObject = (DungeonObject*)extractEntity(&player->objects,&firstHalf);
		if(putObject == nullptr)
		{
			putObject = (DungeonObject*)extractEntity(&room->objects,&firstHalf);
		}

		if(putObject != nullptr)
		{
			removeObject(&room->objects,putObject);
			removeObject(&player->objects,putObject);
			containerObject->contents.push_back(putObject);
			return "You put the "+ putObject->getPrimaryName() + " in the " + containerObject->getPrimaryName() + ".";
		}
		else
		{
			return "You try to but you can't put that there.";
		}
	}

	return "You flounder about, with no success.";
}

string DungeonEngine::take(string args)
{
	DungeonObject* takenObject = (DungeonObject*)extractEntity(&room->objects,&args);
	if(takenObject != nullptr)
	{
		removeObject(&room->objects,takenObject);
	}

	if(takenObject == nullptr)
	{
		for(auto o : room->objects)
		{
			if(o->isOpen) {
				takenObject = (DungeonObject*)extractEntity(&o->contents,&args);
				if(takenObject != nullptr)
				{
					removeObject(&o->contents,takenObject);
					break;
				}
			}
		}

		if(takenObject == nullptr)
		{
			for(auto o : player->objects)
			{
				if(o->isOpen) {
					takenObject = (DungeonObject*)extractEntity(&o->contents,&args);
					if(takenObject != nullptr)
					{
						removeObject(&o->contents,takenObject);
						break;
					}
				}
			}
		}
	}

	if(takenObject != nullptr)
	{
		player->objects.push_back(takenObject);
		return takenObject->getPrimaryName() + " taken.";
	}
	else
	{
		return "You try to take it, but it seems futile";
	}

}
string DungeonEngine::use(string args)
{
	//DungeonObject* roomObject = (DungeonObject*)extractEntity(&room->objects,&args);
	DungeonObject* playerObject = (DungeonObject*)extractEntity(&player->objects,&args);
	DungeonCreature* creature = (DungeonCreature*)extractEntity(&room->creatures,&args);

	if(playerObject != nullptr && creature != nullptr) {
		string response = creature->attack(playerObject,player);
		if(creature->hitpoints <= 0)
		{
			removeCreature(&room->creatures,creature);
		}
		return response;
	}
	else
	{
		return "Your attempt amounts to nothing.";
	}

}

string DungeonEngine::open(string args)
{

	//chceck for objects to open in the room
	DungeonObject* thingToOpen = (DungeonObject*)extractEntity(&room->objects,&args);
	//failing that, check for them on the player
	if(thingToOpen == nullptr)
	{
		thingToOpen = (DungeonObject*)extractEntity(&player->objects,&args);
	}
	//If it is an openable thing, that is not already open, open it!
	if(thingToOpen != nullptr && thingToOpen->canOpen == true && thingToOpen->isOpen == false)
	{
		thingToOpen->isOpen = true;
		textBuffer.push_back("You open the "+thingToOpen->getPrimaryName()+", inside you see " + showContents(thingToOpen));
		return "";
	}
	else if(thingToOpen != nullptr)
	{
		return "You can't open that";
	}

	//Now check for 'doors' to open
	DungeonExit * exitToOpen = (DungeonExit*)extractEntity(&room->exits,&args);
	if(exitToOpen != nullptr && exitToOpen->isDoor && !exitToOpen->isOpen)
	{
		exitToOpen->isOpen = true;
		textBuffer.push_back(exitToOpen->openingText);
	}
	else if(exitToOpen != nullptr)
	{
		return "You try but fail.";
	}

	return "You don't see that here.";
}

void DungeonEngine::move(DungeonExit *dungeonExit)
{
	//if this is not a logical door, of it is open, go!
	if(! dungeonExit->isDoor || dungeonExit->isOpen)
	{
		room = dungeonExit->room;
		look();
	}
	else if(dungeonExit->isDoor && !dungeonExit->isOpen)
	{
		textBuffer.push_back(dungeonExit->closedText);
	}

}

string DungeonEngine::lookCmd(string args)
{
	look();
	return "";
}

void DungeonEngine::clearWindows()
{
	delwin(commandWindow);
	delwin(mainWindow);
	delwin(headerWindow);
	clear();
}

void DungeonEngine::addToBuffer(vector<string> *v)
{
	textBuffer.insert(textBuffer.end(),v->begin(),v->end());
}

void DungeonEngine::resetWindows()
{
	headerWindow = newwin(1,getCols(),0,0);
	commandWindow = newwin(1,getCols(),LINES-1,0);
	keypad(commandWindow,true);

	mainWindow = newwin(LINES-2,getCols(),1,0);
	scrollok(mainWindow,TRUE);
	getmaxyx(stdscr,h,w); // this doesn't work in windows

	init_pair(1,COLOR_BLACK,COLOR_RED);
	wbkgd(headerWindow,COLOR_PAIR(1));

	look();

	refresh();
	wrefresh(headerWindow);
	wrefresh(commandWindow);
	wrefresh(mainWindow);

}

string DungeonEngine::showContents(DungeonObject *o)
{

	string stuffInside;
	if(o->contents.size() == 1)
	{
		stuffInside += a_an(o->contents[0]->getPrimaryName()) +".";
	}
	else
	{
		for(unsigned int i = 0; i < o->contents.size(); i++)
		{

			if(i < o->contents.size()-1) {
				stuffInside += a_an(o->contents[i]->getPrimaryName()) + ", ";
			}
			else {
				stuffInside += "and "+a_an(o->contents[i]->getPrimaryName()) + ".";
			}
		}
	}
	return stuffInside;

}
void DungeonEngine::look()
{
	addToBuffer(&room->description);

	for(auto creature : room->creatures)
	{
		textBuffer.push_back(thereIsA(creature->getPrimaryName()));
	}

	for(auto o : room->objects)
	{
		string objString = thereIsA(o->getPrimaryName())+".";
		if(o->isOpen && o->contents.size() > 0) {
			objString += " Inside it you see ";
			objString += showContents(o);
		}

		textBuffer.push_back(objString);

	}

	for(auto exit : room->exits)
	{

		if(exit->isDoor)
		{
			if(exit->isOpen)
			{
				textBuffer.push_back(exit->openText);
			}
			else
			{
				textBuffer.push_back(exit->closedText);
			}
		}
		else {
			textBuffer.push_back(exit->openText);
		}

	}

}

void DungeonEngine::render(unsigned long offset)
{
	wclear(mainWindow);

	for(auto i = start; i < end; i++)
	{
		string entry = textBuffer[i];
		vector<string> tokens = split(entry,' ');

		int x = 0;
		for(auto s : tokens)
		{
			s = s + " ";
			if(s.length() + x < COLS)
			{
				wprintw(mainWindow,s.c_str());
				x += s.length();
			}
			else {
				wprintw(mainWindow,"\n");

				wprintw(mainWindow,s.c_str());
				x = s.length();
			}
		}
		wprintw(mainWindow,"\n");

		//dbsleep(200);
	}
	wrefresh(mainWindow);
}

void DungeonEngine::updateCmdMap()
{
	cmdMap[STR_EXIT] = &DungeonEngine::exit;
	cmdMap[STR_PAGE_UP] = &DungeonEngine::pageUp;
	cmdMap[STR_PAGE_DOWN] = &DungeonEngine::pageDown;
	cmdMap[STR_USE] = &DungeonEngine::use;
	cmdMap[STR_LOOK_AT] = &DungeonEngine::examine;
	cmdMap[STR_TAKE] = &DungeonEngine::take;
	cmdMap[STR_LOOK] = &DungeonEngine::lookCmd;
	cmdMap[STR_OPEN] = &DungeonEngine::open;
	cmdMap[STR_PUT] = &DungeonEngine::put;
	cmdMap[STR_PLACE] = &DungeonEngine::put;
	cmdMap[STR_EXAMINE] = &DungeonEngine::examine;
	cmdMap[STR_DROP] = &DungeonEngine::drop;

	//iterate over players inventory and add all
	//aliases for the verb 'use' to the cmdMap
	for(auto o : player->objects)
	{
		for(auto alias : o->useAliases)
		{
			cmdMap[alias] = &DungeonEngine::use;
		}
	}

	for(auto o : room->objects)
	{
		for(auto alias : o->useAliases)
		{
			cmdMap[alias] = &DungeonEngine::use;
		}
	}

}

void DungeonEngine::load(DungeonRoom *_room,DungeonPlayer *_player)
{
	player = _player;
	room = _room;
	renderOffset = 0;
	pageSize = LINES - 3;

	//create a map of exit names to move to
	for(auto e : room->exits)
	{
		for(auto s : e->getLcaseNames())
		{
			moveMap[s] = e;
		}
	}

	resetWindows();

	CommandWindow cmdW;

	while(true) {
		updateCmdMap();
		wmove(headerWindow,0,0);
		wclrtoeol(headerWindow);
		mvwprintw(headerWindow,0,0,"Dungeon Builder");
		mvwprintwCenter(headerWindow,0,room->getPrimaryName().c_str());
		wrefresh(headerWindow);
		render(renderOffset);
		string userInput = cmdW.getCommandAsString(commandWindow,STR_PROMPT);
		textBuffer.push_back(STR_PROMPT+userInput);

		if(userInput.length() > 0) {

			vector<string> verbs;
			for(map<string,commandFunction>::iterator it = cmdMap.begin(); it != cmdMap.end(); ++it) {
				verbs.push_back(it->first);
			}

			string verb = extractPhrase(verbs,&userInput);

			if(verb == "") {
				vector<string> directions;
				for(map<string,DungeonExit*>::iterator it = moveMap.begin(); it != moveMap.end(); ++it) {
					directions.push_back(it->first);
				}

				string moveStr = extractPhrase(directions,&userInput);

				if(moveStr == "") {
					textBuffer.push_back("What are you doing, dave?");
				}
				else
				{
					move(moveMap[moveStr]);
				}
			}
			else
			{
				if (verb == STR_EXIT) break;
				commandFunction cmdFunc = cmdMap[verb];
				string response = (this->*cmdFunc)(userInput);
				if(response.length() > 1) {
					textBuffer.push_back(response);
				}

			}
		}

	}

	clearWindows();
}
<commit_msg>working on pageup/down<commit_after>#include "dungeon_engine.h"
#include "printutils.h"
#include "utils.h"
#include "command_window.h"
#include "string_constants.h"

using namespace std;

string DungeonEngine::exit(string args)
{
	return STR_EXIT;
}

string DungeonEngine::pageUp(string args)
{
	renderOffset = min(renderOffset+25,textBuffer.size());
	return "";
}

string DungeonEngine::pageDown(string args)
{
	renderOffset = max(0,renderOffset - 25);
	return "";
}

string DungeonEngine::drop(string args)
{
	DungeonObject *thing = (DungeonObject*)extractEntity(&player->objects,&args);
	if(thing != nullptr) {
		removeObject(&player->objects,thing);
		room->objects.push_back(thing);
		return "You drop the " + thing->getPrimaryName() +".";
	}
	else {
		return "You don't have that.";
	}
}

string DungeonEngine::examine(string args)
{
	DungeonObject* thing =(DungeonObject*)extractEntity(&room->objects,&args);
	if(thing == nullptr)
	{
		thing = (DungeonObject*)extractEntity(&player->objects,&args);
	}

	if(thing != nullptr && thing->description.size() == 0)
	{
		return "You see no further detail.";

	}
	else if(thing != nullptr)
	{
		addToBuffer(&thing->description);
		return "";
	}
	else {
		DungeonCreature *gal = (DungeonCreature*)extractEntity(&room->creatures,&args);
		if(gal != nullptr)
		{
			if(gal->description.size() == 0)
			{
				return "There is nothing more to see.";
			}
			else {
				addToBuffer(&gal->description);
				return "";
			}
		}
		else
		{
			return "You don't see that here.";
		}
	}

	return "investigate examine function more";
}

string DungeonEngine::put(string args)
{
	//get the string before and after the word "in" to clarify what is being put where
	unsigned long inLocation = args.find(" in ");
	if(inLocation == string::npos)
	{
		return "Your fumble about, but it doesn't work.";
	}

	string firstHalf = args.substr(0,inLocation);
	string secondHalf = args.substr(inLocation+4,args.size()-(inLocation+4));

	DungeonObject* containerObject =  (DungeonObject*)extractEntity(&player->objects,&secondHalf);
	if(containerObject == nullptr)
	{
		containerObject = (DungeonObject*)extractEntity(&room->objects,&secondHalf);
	}

	if(containerObject != nullptr && containerObject->isOpen)
	{
		DungeonObject* putObject = (DungeonObject*)extractEntity(&player->objects,&firstHalf);
		if(putObject == nullptr)
		{
			putObject = (DungeonObject*)extractEntity(&room->objects,&firstHalf);
		}

		if(putObject != nullptr)
		{
			removeObject(&room->objects,putObject);
			removeObject(&player->objects,putObject);
			containerObject->contents.push_back(putObject);
			return "You put the "+ putObject->getPrimaryName() + " in the " + containerObject->getPrimaryName() + ".";
		}
		else
		{
			return "You try to but you can't put that there.";
		}
	}

	return "You flounder about, with no success.";
}

string DungeonEngine::take(string args)
{
	DungeonObject* takenObject = (DungeonObject*)extractEntity(&room->objects,&args);
	if(takenObject != nullptr)
	{
		removeObject(&room->objects,takenObject);
	}

	if(takenObject == nullptr)
	{
		for(auto o : room->objects)
		{
			if(o->isOpen) {
				takenObject = (DungeonObject*)extractEntity(&o->contents,&args);
				if(takenObject != nullptr)
				{
					removeObject(&o->contents,takenObject);
					break;
				}
			}
		}

		if(takenObject == nullptr)
		{
			for(auto o : player->objects)
			{
				if(o->isOpen) {
					takenObject = (DungeonObject*)extractEntity(&o->contents,&args);
					if(takenObject != nullptr)
					{
						removeObject(&o->contents,takenObject);
						break;
					}
				}
			}
		}
	}

	if(takenObject != nullptr)
	{
		player->objects.push_back(takenObject);
		return takenObject->getPrimaryName() + " taken.";
	}
	else
	{
		return "You try to take it, but it seems futile";
	}

}
string DungeonEngine::use(string args)
{
	//DungeonObject* roomObject = (DungeonObject*)extractEntity(&room->objects,&args);
	DungeonObject* playerObject = (DungeonObject*)extractEntity(&player->objects,&args);
	DungeonCreature* creature = (DungeonCreature*)extractEntity(&room->creatures,&args);

	if(playerObject != nullptr && creature != nullptr) {
		string response = creature->attack(playerObject,player);
		if(creature->hitpoints <= 0)
		{
			removeCreature(&room->creatures,creature);
		}
		return response;
	}
	else
	{
		return "Your attempt amounts to nothing.";
	}

}

string DungeonEngine::open(string args)
{

	//chceck for objects to open in the room
	DungeonObject* thingToOpen = (DungeonObject*)extractEntity(&room->objects,&args);
	//failing that, check for them on the player
	if(thingToOpen == nullptr)
	{
		thingToOpen = (DungeonObject*)extractEntity(&player->objects,&args);
	}
	//If it is an openable thing, that is not already open, open it!
	if(thingToOpen != nullptr && thingToOpen->canOpen == true && thingToOpen->isOpen == false)
	{
		thingToOpen->isOpen = true;
		textBuffer.push_back("You open the "+thingToOpen->getPrimaryName()+", inside you see " + showContents(thingToOpen));
		return "";
	}
	else if(thingToOpen != nullptr)
	{
		return "You can't open that";
	}

	//Now check for 'doors' to open
	DungeonExit * exitToOpen = (DungeonExit*)extractEntity(&room->exits,&args);
	if(exitToOpen != nullptr && exitToOpen->isDoor && !exitToOpen->isOpen)
	{
		exitToOpen->isOpen = true;
		textBuffer.push_back(exitToOpen->openingText);
	}
	else if(exitToOpen != nullptr)
	{
		return "You try but fail.";
	}

	return "You don't see that here.";
}

void DungeonEngine::move(DungeonExit *dungeonExit)
{
	//if this is not a logical door, of it is open, go!
	if(! dungeonExit->isDoor || dungeonExit->isOpen)
	{
		room = dungeonExit->room;
		look();
	}
	else if(dungeonExit->isDoor && !dungeonExit->isOpen)
	{
		textBuffer.push_back(dungeonExit->closedText);
	}

}

string DungeonEngine::lookCmd(string args)
{
	look();
	return "";
}

void DungeonEngine::clearWindows()
{
	delwin(commandWindow);
	delwin(mainWindow);
	delwin(headerWindow);
	clear();
}

void DungeonEngine::addToBuffer(vector<string> *v)
{
	textBuffer.insert(textBuffer.end(),v->begin(),v->end());
}

void DungeonEngine::resetWindows()
{
	headerWindow = newwin(1,getCols(),0,0);
	commandWindow = newwin(1,getCols(),LINES-1,0);
	keypad(commandWindow,true);

	mainWindow = newwin(LINES-2,getCols(),1,0);
	scrollok(mainWindow,TRUE);
	getmaxyx(stdscr,h,w); // this doesn't work in windows

	init_pair(1,COLOR_BLACK,COLOR_RED);
	wbkgd(headerWindow,COLOR_PAIR(1));

	look();

	refresh();
	wrefresh(headerWindow);
	wrefresh(commandWindow);
	wrefresh(mainWindow);

}

string DungeonEngine::showContents(DungeonObject *o)
{

	string stuffInside;
	if(o->contents.size() == 1)
	{
		stuffInside += a_an(o->contents[0]->getPrimaryName()) +".";
	}
	else
	{
		for(unsigned int i = 0; i < o->contents.size(); i++)
		{

			if(i < o->contents.size()-1) {
				stuffInside += a_an(o->contents[i]->getPrimaryName()) + ", ";
			}
			else {
				stuffInside += "and "+a_an(o->contents[i]->getPrimaryName()) + ".";
			}
		}
	}
	return stuffInside;

}
void DungeonEngine::look()
{
	addToBuffer(&room->description);

	for(auto creature : room->creatures)
	{
		textBuffer.push_back(thereIsA(creature->getPrimaryName()));
	}

	for(auto o : room->objects)
	{
		string objString = thereIsA(o->getPrimaryName())+".";
		if(o->isOpen && o->contents.size() > 0) {
			objString += " Inside it you see ";
			objString += showContents(o);
		}

		textBuffer.push_back(objString);

	}

	for(auto exit : room->exits)
	{

		if(exit->isDoor)
		{
			if(exit->isOpen)
			{
				textBuffer.push_back(exit->openText);
			}
			else
			{
				textBuffer.push_back(exit->closedText);
			}
		}
		else {
			textBuffer.push_back(exit->openText);
		}

	}

}

void DungeonEngine::render(unsigned long offset)
{
	wclear(mainWindow);
	//todo implement for real
	int start = 0;
	int end = textBuffer.size();
	for(auto i = start; i < end; i++)
	{
		string entry = textBuffer[i];
		vector<string> tokens = split(entry,' ');

		int x = 0;
		for(auto s : tokens)
		{
			s = s + " ";
			if(s.length() + x < COLS)
			{
				wprintw(mainWindow,s.c_str());
				x += s.length();
			}
			else {
				wprintw(mainWindow,"\n");

				wprintw(mainWindow,s.c_str());
				x = s.length();
			}
		}
		wprintw(mainWindow,"\n");

		//dbsleep(200);
	}
	wrefresh(mainWindow);
}

void DungeonEngine::updateCmdMap()
{
	cmdMap[STR_EXIT] = &DungeonEngine::exit;
	cmdMap[STR_PAGE_UP] = &DungeonEngine::pageUp;
	cmdMap[STR_PAGE_DOWN] = &DungeonEngine::pageDown;
	cmdMap[STR_USE] = &DungeonEngine::use;
	cmdMap[STR_LOOK_AT] = &DungeonEngine::examine;
	cmdMap[STR_TAKE] = &DungeonEngine::take;
	cmdMap[STR_LOOK] = &DungeonEngine::lookCmd;
	cmdMap[STR_OPEN] = &DungeonEngine::open;
	cmdMap[STR_PUT] = &DungeonEngine::put;
	cmdMap[STR_PLACE] = &DungeonEngine::put;
	cmdMap[STR_EXAMINE] = &DungeonEngine::examine;
	cmdMap[STR_DROP] = &DungeonEngine::drop;

	//iterate over players inventory and add all
	//aliases for the verb 'use' to the cmdMap
	for(auto o : player->objects)
	{
		for(auto alias : o->useAliases)
		{
			cmdMap[alias] = &DungeonEngine::use;
		}
	}

	for(auto o : room->objects)
	{
		for(auto alias : o->useAliases)
		{
			cmdMap[alias] = &DungeonEngine::use;
		}
	}

}

void DungeonEngine::load(DungeonRoom *_room,DungeonPlayer *_player)
{
	player = _player;
	room = _room;
	renderOffset = 0;
	pageSize = LINES - 3;

	//create a map of exit names to move to
	for(auto e : room->exits)
	{
		for(auto s : e->getLcaseNames())
		{
			moveMap[s] = e;
		}
	}

	resetWindows();

	CommandWindow cmdW;

	while(true) {
		updateCmdMap();
		wmove(headerWindow,0,0);
		wclrtoeol(headerWindow);
		mvwprintw(headerWindow,0,0,"Dungeon Builder");
		mvwprintwCenter(headerWindow,0,room->getPrimaryName().c_str());
		wrefresh(headerWindow);
		render(renderOffset);
		string userInput = cmdW.getCommandAsString(commandWindow,STR_PROMPT);
		textBuffer.push_back(STR_PROMPT+userInput);

		if(userInput.length() > 0) {

			vector<string> verbs;
			for(map<string,commandFunction>::iterator it = cmdMap.begin(); it != cmdMap.end(); ++it) {
				verbs.push_back(it->first);
			}

			string verb = extractPhrase(verbs,&userInput);

			if(verb == "") {
				vector<string> directions;
				for(map<string,DungeonExit*>::iterator it = moveMap.begin(); it != moveMap.end(); ++it) {
					directions.push_back(it->first);
				}

				string moveStr = extractPhrase(directions,&userInput);

				if(moveStr == "") {
					textBuffer.push_back("What are you doing, dave?");
				}
				else
				{
					move(moveMap[moveStr]);
				}
			}
			else
			{
				if (verb == STR_EXIT) break;
				commandFunction cmdFunc = cmdMap[verb];
				string response = (this->*cmdFunc)(userInput);
				if(response.length() > 1) {
					textBuffer.push_back(response);
				}

			}
		}

	}

	clearWindows();
}
<|endoftext|>


<commit_before>/*************************************************************************
*
*  $RCSfile: binarycache.cxx,v $
*
*  $Revision: 1.3 $
*
*  last change: $Author: hr $ $Date: 2003-06-30 14:07:30 $
*
*  The Contents of this file are made available subject to the terms of
*  either of the following licenses
*
*         - GNU Lesser General Public License Version 2.1
*         - Sun Industry Standards Source License Version 1.1
*
*  Sun Microsystems Inc., October, 2000
*
*  GNU Lesser General Public License Version 2.1
*  =============================================
*  Copyright 2000 by Sun Microsystems, Inc.
*  901 San Antonio Road, Palo Alto, CA 94303, USA
*
*  This library is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Lesser General Public
*  License version 2.1, as published by the Free Software Foundation.
*
*  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., 59 Temple Place, Suite 330, Boston,
*  MA  02111-1307  USA
*
*
*  Sun Industry Standards Source License Version 1.1
*  =================================================
*  The contents of this file are subject to the Sun Industry Standards
*  Source License Version 1.1 (the "License"); You may not use this file
*  except in compliance with the License. You may obtain a copy of the
*  License at http://www.openoffice.org/license.html.
*
*  Software provided under this License is provided on an "AS IS" basis,
*  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
*  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
*  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
*  See the License for the specific provisions governing your rights and
*  obligations concerning the Software.
*
*  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
*
*  Copyright: 2002 by Sun Microsystems, Inc.
*
*  All Rights Reserved.
*
*  Contributor(s): _______________________________________
*
*
************************************************************************/

#include "binarycache.hxx"

#include "binaryreadhandler.hxx"
#include "binarywritehandler.hxx"

#include "mergedcomponentdata.hxx"

#ifndef _CONFIGMGR_FILEHELPER_HXX_
#include "filehelper.hxx"
#endif

#ifndef CONFIGMGR_TYPECONVERTER_HXX
#include "typeconverter.hxx"
#endif

#ifndef _CONFIGMGR_BOOTSTRAP_HXX
#include "bootstrap.hxx"
#endif

#ifndef _OSL_FILE_HXX_
#include <osl/file.hxx>
#endif
#ifndef _OSL_PROCESS_H_
#include <osl/process.h>
#endif

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif // _RTL_USTRBUF_HXX_

#ifndef _RTL_LOGFILE_HXX_
#include <rtl/logfile.hxx>
#endif

#define RTL_LOGFILE_OU2A(rtlOUString)   (::rtl::OUStringToOString((rtlOUString), RTL_TEXTENCODING_ASCII_US).getStr())

namespace configmgr
{
    // -----------------------------------------------------------------------------
    namespace backend
    {

        using ::rtl::OUString;

        const OUString aSettingName(
                RTL_CONSTASCII_USTRINGPARAM( CONTEXT_ITEM_PREFIX_ "CacheUrl"));
        // ---------------------------------------------------------------------------------------
        static inline bool isValidFileURL (OUString const& _sFileURL)
        {
            using osl::File;

            OUString sSystemPath;
            return _sFileURL.getLength() && (File::E_None == File::getSystemPathFromFileURL(_sFileURL, sSystemPath));
        }
        // -----------------------------------------------------------------------------
        // ---------------------------------------------------------------------------------------
        static
        bool implEnsureAbsoluteURL(rtl::OUString & _rsURL) // also strips embedded dots etc.
        {
            using osl::File;
            if (!_rsURL.getLength())
                return false;

            if (!isValidFileURL(_rsURL))
            {
                OSL_TRACE("Binary cache: File URL %s is invalid.",
                            rtl::OUStringToOString(_rsURL,RTL_TEXTENCODING_ASCII_US).getStr());
                return false;
            }

            rtl::OUString sBasePath = _rsURL;
            OSL_VERIFY(osl_Process_E_None == osl_getProcessWorkingDir(&sBasePath.pData));

            rtl::OUString sAbsolute;
            if ( File::E_None == File::getAbsoluteFileURL(sBasePath, _rsURL, sAbsolute))
            {
                _rsURL = sAbsolute;
                return isValidFileURL(_rsURL);
            }
            else
            {
                OSL_ENSURE(!isValidFileURL(_rsURL), "Could not get absolute file URL for valid URL");
                return false;
            }
        }
        // ---------------------------------------------------------------------------------------
        static const sal_Unicode kComponentSeparator = '.' ;
        static const sal_Unicode kPathSeparator = '/' ;
        static const char kBinarySuffix[] = ".dat" ;

        OUString BinaryCache::getCacheFileURL(const OUString& aComponent) const
        {
            rtl::OUStringBuffer retCode (mBaseURL);
            retCode.append(kPathSeparator) ;
        //  retCode.append(aComponent.replace(kComponentSeparator, kPathSeparator)) ;
            retCode.append(aComponent) ;
            retCode.appendAscii(RTL_CONSTASCII_STRINGPARAM(kBinarySuffix));

            OUString aResult = retCode.makeStringAndClear() ;

            if (isValidFileURL(aResult))
            {
                return aResult;
            }
            else
            {
                OSL_ENSURE(false, "Component File URL is invalid");
                return OUString();
            }
        }
        // -----------------------------------------------------------------------------
        BinaryCache::BinaryCache(const uno::Reference<uno::XComponentContext>& xContext )
        : mBaseURL()
        , mOwnerEntity()
        , mbCacheEnabled(false)
        {

            //initialise the base URL
            ContextReader aReader(xContext);

            OUString sCacheUrl;
            if (!aReader.isAdminService())
            {
                mbCacheEnabled = (aReader.getBestContext()->getValueByName(aSettingName) >>= sCacheUrl)
                                        && implEnsureAbsoluteURL(sCacheUrl);
            }

            if (mbCacheEnabled)
            {
                mBaseURL = sCacheUrl;
                if (!FileHelper::dirExists(sCacheUrl))
                {
                    if (osl::File::RC errorCode = FileHelper::mkdirs(sCacheUrl))
                    {
#if (OSL_DEBUG_LEVEL > 0)
                        rtl::OString sURL = rtl::OUStringToOString(sCacheUrl,RTL_TEXTENCODING_ASCII_US);
                        rtl::OString sErr = rtl::OUStringToOString(FileHelper::createOSLErrorString(errorCode),RTL_TEXTENCODING_ASCII_US);
                        ::osl_trace("Configuration: Cannot create cache directory \"%s\". "
                                    "Error is %s [%d]",sURL.getStr(),sErr.getStr(),int(errorCode)) ;
#endif
                        mbCacheEnabled = false;
                    }
                }
            }
        }
        // -----------------------------------------------------------------------------

        void BinaryCache::setOwnerEntity(const OUString & aOwnerEntity)
        {
            OSL_PRECOND(mOwnerEntity.getLength() == 0, "Owner entity of cache already set");
            mOwnerEntity = aOwnerEntity;
        }
        // -----------------------------------------------------------------------------

        void BinaryCache::disableCache()
        {
            mbCacheEnabled = false;
        }
        // -----------------------------------------------------------------------------

        bool BinaryCache::isCacheEnabled(rtl::OUString const & aEntity) const
        {
            if (!mbCacheEnabled) return false;

            // default entity is empty
            if (aEntity.getLength() == 0) return true;

            return aEntity.equals(mOwnerEntity);
        }
        // -----------------------------------------------------------------------------

        bool BinaryCache::readComponentData(MergedComponentData & aComponentData,
                                MultiServiceFactory const & aFactory,
                                OUString const & aComponent,
                                OUString const & aEntity,
                                OUString const & aLocale,
                                const uno::Reference<backenduno::XLayer> * pLayers,
                                sal_Int32 nNumLayers,
                                bool bIncludeTemplates)
        {
            if (isCacheEnabled(aEntity))
            try
            {
                RTL_LOGFILE_CONTEXT_AUTHOR(aLog, "configmgr::backend::BinaryCache", "jb99855", "configmgr: BinaryCache::readComponentData() - enabled");
                BinaryReadHandler aCacheReader(getCacheFileURL(aComponent),aComponent,aFactory);

                if(aCacheReader.validateHeader(pLayers, nNumLayers, mOwnerEntity, aLocale ))
                {
                    RTL_LOGFILE_CONTEXT_AUTHOR(aLog1, "configmgr::backend::BinaryCache", "jb99855", "configmgr: BinaryCache::readComponentData() - cache hit");
                    aComponentData.setSchemaRoot( aCacheReader.readComponentTree() );
                    if (bIncludeTemplates)
                        aComponentData.setTemplatesTree( aCacheReader.readTemplatesTree() );
                    return true;
                }
            }
            catch (uno::Exception & e)
            {
                OSL_TRACE("Binary Cache read failed - exception: %s", rtl::OUStringToOString(e.Message,RTL_TEXTENCODING_ASCII_US).getStr());
            }
            return false;
        }
        // -----------------------------------------------------------------------------

        bool BinaryCache::writeComponentData(MergedComponentData const & aComponentData,
                                MultiServiceFactory const & aFactory,
                                OUString const & aComponent,
                                OUString const & aEntity,
                                OUString const & aLocale,
                                const uno::Reference<backenduno::XLayer> * pLayers,
                                sal_Int32 nNumLayers)
        {
            if (isCacheEnabled(aEntity))
            try
            {
                RTL_LOGFILE_CONTEXT_AUTHOR(aLog3, "configmgr::backend::BinaryCache", "jb99855", "configmgr: BinaryCache::writeComponentData() - enabled");
                BinaryWriteHandler aCacheWriter(getCacheFileURL(aComponent),aComponent, aFactory);

                //write data to cache
                if (aCacheWriter.generateHeader(pLayers, nNumLayers, mOwnerEntity, aLocale))
                {
                    aCacheWriter.writeComponentTree(aComponentData.getSchemaTree());
                    aCacheWriter.writeTemplatesTree(aComponentData.getTemplatesTree());
                    return true;
                }
            }
            catch (uno::Exception & e)
            {
                OSL_TRACE("Configuration: Cache write failed - exception: %s", rtl::OUStringToOString(e.Message,RTL_TEXTENCODING_ASCII_US).getStr());
            }
            return false;
        }
        // -----------------------------------------------------------------------------

    }
// -----------------------------------------------------------------------------
}
<commit_msg>INTEGRATION: CWS cfgsmartcache (1.3.122); FILE MERGED 2005/01/12 15:32:38 jb 1.3.122.1: #i29624# Multilocale support for the binary cache<commit_after>/*************************************************************************
*
*  $RCSfile: binarycache.cxx,v $
*
*  $Revision: 1.4 $
*
*  last change: $Author: kz $ $Date: 2005-01-18 13:28:22 $
*
*  The Contents of this file are made available subject to the terms of
*  either of the following licenses
*
*         - GNU Lesser General Public License Version 2.1
*         - Sun Industry Standards Source License Version 1.1
*
*  Sun Microsystems Inc., October, 2000
*
*  GNU Lesser General Public License Version 2.1
*  =============================================
*  Copyright 2000 by Sun Microsystems, Inc.
*  901 San Antonio Road, Palo Alto, CA 94303, USA
*
*  This library is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Lesser General Public
*  License version 2.1, as published by the Free Software Foundation.
*
*  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., 59 Temple Place, Suite 330, Boston,
*  MA  02111-1307  USA
*
*
*  Sun Industry Standards Source License Version 1.1
*  =================================================
*  The contents of this file are subject to the Sun Industry Standards
*  Source License Version 1.1 (the "License"); You may not use this file
*  except in compliance with the License. You may obtain a copy of the
*  License at http://www.openoffice.org/license.html.
*
*  Software provided under this License is provided on an "AS IS" basis,
*  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
*  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
*  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
*  See the License for the specific provisions governing your rights and
*  obligations concerning the Software.
*
*  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
*
*  Copyright: 2002 by Sun Microsystems, Inc.
*
*  All Rights Reserved.
*
*  Contributor(s): _______________________________________
*
*
************************************************************************/

#include "binarycache.hxx"

#include "binaryreadhandler.hxx"
#include "binarywritehandler.hxx"

#include "mergedcomponentdata.hxx"

#ifndef _CONFIGMGR_FILEHELPER_HXX_
#include "filehelper.hxx"
#endif

#ifndef CONFIGMGR_TYPECONVERTER_HXX
#include "typeconverter.hxx"
#endif

#ifndef _CONFIGMGR_BOOTSTRAP_HXX
#include "bootstrap.hxx"
#endif

#ifndef _OSL_FILE_HXX_
#include <osl/file.hxx>
#endif
#ifndef _OSL_PROCESS_H_
#include <osl/process.h>
#endif

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif // _RTL_USTRBUF_HXX_

#ifndef _RTL_LOGFILE_HXX_
#include <rtl/logfile.hxx>
#endif

#define RTL_LOGFILE_OU2A(rtlOUString)   (::rtl::OUStringToOString((rtlOUString), RTL_TEXTENCODING_ASCII_US).getStr())

namespace configmgr
{
    // -----------------------------------------------------------------------------
    namespace backend
    {

        using ::rtl::OUString;

        const OUString aSettingName(
                RTL_CONSTASCII_USTRINGPARAM( CONTEXT_ITEM_PREFIX_ "CacheUrl"));
        // ---------------------------------------------------------------------------------------
        static inline bool isValidFileURL (OUString const& _sFileURL)
        {
            using osl::File;

            OUString sSystemPath;
            return _sFileURL.getLength() && (File::E_None == File::getSystemPathFromFileURL(_sFileURL, sSystemPath));
        }
        // -----------------------------------------------------------------------------
        // ---------------------------------------------------------------------------------------
        static
        bool implEnsureAbsoluteURL(rtl::OUString & _rsURL) // also strips embedded dots etc.
        {
            using osl::File;
            if (!_rsURL.getLength())
                return false;

            if (!isValidFileURL(_rsURL))
            {
                OSL_TRACE("Binary cache: File URL %s is invalid.",
                            rtl::OUStringToOString(_rsURL,RTL_TEXTENCODING_ASCII_US).getStr());
                return false;
            }

            rtl::OUString sBasePath = _rsURL;
            OSL_VERIFY(osl_Process_E_None == osl_getProcessWorkingDir(&sBasePath.pData));

            rtl::OUString sAbsolute;
            if ( File::E_None == File::getAbsoluteFileURL(sBasePath, _rsURL, sAbsolute))
            {
                _rsURL = sAbsolute;
                return isValidFileURL(_rsURL);
            }
            else
            {
                OSL_ENSURE(!isValidFileURL(_rsURL), "Could not get absolute file URL for valid URL");
                return false;
            }
        }
        // ---------------------------------------------------------------------------------------
        static const sal_Unicode kComponentSeparator = '.' ;
        static const sal_Unicode kPathSeparator = '/' ;
        static const char kBinarySuffix[] = ".dat" ;

        OUString BinaryCache::getCacheFileURL(const OUString& aComponent) const
        {
            rtl::OUStringBuffer retCode (mBaseURL);
            retCode.append(kPathSeparator) ;
        //  retCode.append(aComponent.replace(kComponentSeparator, kPathSeparator)) ;
            retCode.append(aComponent) ;
            retCode.appendAscii(RTL_CONSTASCII_STRINGPARAM(kBinarySuffix));

            OUString aResult = retCode.makeStringAndClear() ;

            if (isValidFileURL(aResult))
            {
                return aResult;
            }
            else
            {
                OSL_ENSURE(false, "Component File URL is invalid");
                return OUString();
            }
        }
        // -----------------------------------------------------------------------------
        BinaryCache::BinaryCache(const uno::Reference<uno::XComponentContext>& xContext )
        : mBaseURL()
        , mOwnerEntity()
        , mbCacheEnabled(false)
        {

            //initialise the base URL
            ContextReader aReader(xContext);

            OUString sCacheUrl;
            if (!aReader.isAdminService())
            {
                mbCacheEnabled = (aReader.getBestContext()->getValueByName(aSettingName) >>= sCacheUrl)
                                        && implEnsureAbsoluteURL(sCacheUrl);
            }

            if (mbCacheEnabled)
            {
                mBaseURL = sCacheUrl;
                if (!FileHelper::dirExists(sCacheUrl))
                {
                    if (osl::File::RC errorCode = FileHelper::mkdirs(sCacheUrl))
                    {
#if (OSL_DEBUG_LEVEL > 0)
                        rtl::OString sURL = rtl::OUStringToOString(sCacheUrl,RTL_TEXTENCODING_ASCII_US);
                        rtl::OString sErr = rtl::OUStringToOString(FileHelper::createOSLErrorString(errorCode),RTL_TEXTENCODING_ASCII_US);
                        ::osl_trace("Configuration: Cannot create cache directory \"%s\". "
                                    "Error is %s [%d]",sURL.getStr(),sErr.getStr(),int(errorCode)) ;
#endif
                        mbCacheEnabled = false;
                    }
                }
            }
        }
        // -----------------------------------------------------------------------------

        void BinaryCache::setOwnerEntity(const OUString & aOwnerEntity)
        {
            OSL_PRECOND(mOwnerEntity.getLength() == 0, "Owner entity of cache already set");
            mOwnerEntity = aOwnerEntity;
        }
        // -----------------------------------------------------------------------------

        void BinaryCache::disableCache()
        {
            mbCacheEnabled = false;
        }
        // -----------------------------------------------------------------------------

        bool BinaryCache::isCacheEnabled(rtl::OUString const & aEntity) const
        {
            if (!mbCacheEnabled) return false;

            // default entity is empty
            if (aEntity.getLength() == 0) return true;

            return aEntity.equals(mOwnerEntity);
        }
        // -----------------------------------------------------------------------------
        const OUString k_DefaultOwner( RTL_CONSTASCII_USTRINGPARAM( "$(DefaultData)"));

        bool BinaryCache::readComponentData(MergedComponentData & aComponentData,
                                MultiServiceFactory const & aFactory,
                                OUString const & aComponent,
                                OUString const & aEntity,
                                localehelper::Locale const & aRequestedLocale,
                                localehelper::LocaleSequence & outKnownLocales,
                                const uno::Reference<backenduno::XLayer> * pLayers,
                                sal_Int32 nNumLayers,
                                bool bIncludeTemplates)
        {
            if (isCacheEnabled(aEntity))
            try
            {
                RTL_LOGFILE_CONTEXT_AUTHOR(aLog, "configmgr::backend::BinaryCache", "jb99855", "configmgr: BinaryCache::readComponentData() - enabled");
                BinaryReadHandler aCacheReader(getCacheFileURL(aComponent),aComponent,aFactory);

                if(aCacheReader.validateHeader(pLayers, nNumLayers, k_DefaultOwner, aRequestedLocale, outKnownLocales))
                {
                    RTL_LOGFILE_CONTEXT_AUTHOR(aLog1, "configmgr::backend::BinaryCache", "jb99855", "configmgr: BinaryCache::readComponentData() - cache hit");
                    aComponentData.setSchemaRoot( aCacheReader.readComponentTree() );
                    if (bIncludeTemplates)
                        aComponentData.setTemplatesTree( aCacheReader.readTemplatesTree() );
                    return true;
                }
            }
            catch (uno::Exception & e)
            {
                OSL_TRACE("Binary Cache read failed - exception: %s", rtl::OUStringToOString(e.Message,RTL_TEXTENCODING_ASCII_US).getStr());
            }
            return false;
        }
        // -----------------------------------------------------------------------------

        bool BinaryCache::writeComponentData(MergedComponentData const & aComponentData,
                                MultiServiceFactory const & aFactory,
                                OUString const & aComponent,
                                OUString const & aEntity,
                                localehelper::LocaleSequence const & aKnownLocales,
                                const uno::Reference<backenduno::XLayer> * pLayers,
                                sal_Int32 nNumLayers)
        {
            if (isCacheEnabled(aEntity))
            try
            {
                RTL_LOGFILE_CONTEXT_AUTHOR(aLog3, "configmgr::backend::BinaryCache", "jb99855", "configmgr: BinaryCache::writeComponentData() - enabled");
                BinaryWriteHandler aCacheWriter(getCacheFileURL(aComponent),aComponent, aFactory);

                //write data to cache
                if (aCacheWriter.generateHeader(pLayers, nNumLayers, k_DefaultOwner, aKnownLocales))
                {
                    aCacheWriter.writeComponentTree(aComponentData.getSchemaTree());
                    aCacheWriter.writeTemplatesTree(aComponentData.getTemplatesTree());
                    return true;
                }
            }
            catch (uno::Exception & e)
            {
                OSL_TRACE("Configuration: Cache write failed - exception: %s", rtl::OUStringToOString(e.Message,RTL_TEXTENCODING_ASCII_US).getStr());
            }
            return false;
        }
        // -----------------------------------------------------------------------------

    }
// -----------------------------------------------------------------------------
}
<|endoftext|>


<commit_before><commit_msg>submit A.cpp to 'A - ばらばらロボット' (future-contest-2019-qual) [C++14 (GCC 5.4.1)]<commit_after><|endoftext|>


<commit_before>/*
Allocore Example: Texture

Description:
This demonstrates how to create and display a texture.

Author:
Lance Putnam, Nov. 2013
*/

#include "allocore/io/al_App.hpp"
using namespace al;

class MyApp : public App{
public:

	Texture tex;

	MyApp():
		// Construct texture
		// Arguments: width, height, pixel format, pixel data type
		// Note that when we construct a texture in this way, the default
		// policy is to allocate a client-side buffer to hold the pixels.
		tex(64,64, Graphics::RGBA, Graphics::UBYTE)
	{
		// The default magnification filter is linear
		//tex.filterMag(Texture::NEAREST);

		// Get a pointer to the (client-side) pixel buffer.
		// When we make a read access to the pixels, they are flagged as dirty
		// and get sent to the GPU the next time the texture bound.
		unsigned char * pixels = tex.data<unsigned char>();

		// Loop through the pixels to generate an image
		int Nx = tex.width();
		int Ny = tex.height();
		for(int j=0; j<Ny; ++j){ float y = float(j)/(Ny-1)*2-1;
		for(int i=0; i<Nx; ++i){ float x = float(i)/(Nx-1)*2-1;

			float m = 1 - al::clip(hypot(x,y));
			float a = al::wrap(atan2(y,x)/M_2PI);

			Color col = HSV(a,1,m);

			int idx = j*Nx + i;
			int stride = tex.numComponents();
			pixels[idx*stride + 0] = col.r * 255.;
			pixels[idx*stride + 1] = col.g * 255.;
			pixels[idx*stride + 2] = col.b * 255.;
			pixels[idx*stride + 3] = col.a;
		}}

		nav().pos().set(0,0,4);
		initWindow();
	}

	void onDraw(Graphics& g){

		// Borrow a temporary Mesh from Graphics
		Mesh& m = g.mesh();

		m.reset();

		// Generate geometry
		m.primitive(Graphics::TRIANGLE_STRIP);
		m.vertex(-1,  1);
		m.vertex(-1, -1);
		m.vertex( 1,  1);
		m.vertex( 1, -1);

		// Add texture coordinates
		m.texCoord(0,1);
		m.texCoord(0,0);
		m.texCoord(1,1);
		m.texCoord(1,0);

		// We must tell the GPU to use the texture when rendering primitives
		tex.bind();
			g.draw(m);
		tex.unbind();
	}
};

int main(){
	MyApp().start();
}
<commit_msg>Update texture example<commit_after>/*
Allocore Example: Texture

Description:
This demonstrates how to create and display a texture.

Author:
Lance Putnam, Nov. 2013
*/

#include "allocore/io/al_App.hpp"
using namespace al;

class MyApp : public App{
public:

	Texture tex;
	Mesh mesh;

	MyApp():
		// Construct texture
		// Arguments: width, height, pixel format, pixel data type
		// Note that when we construct a texture in this way, the default
		// policy is to allocate a client-side buffer to hold the pixels.
		tex(64,64, Graphics::RGBA, Graphics::UBYTE)
	{
		// The default magnification filter is linear
		//tex.filterMag(Texture::NEAREST);

		// Get a pointer to the (client-side) pixel buffer.
		// When we make a read access to the pixels, they are flagged as dirty
		// and get sent to the GPU the next time the texture is bound.
		unsigned char * pixels = tex.data<unsigned char>();

		// Loop through the pixels to generate an image
		int Nx = tex.width();
		int Ny = tex.height();
		for(int j=0; j<Ny; ++j){ float y = float(j)/(Ny-1)*2-1;
		for(int i=0; i<Nx; ++i){ float x = float(i)/(Nx-1)*2-1;

			float m = 1 - al::clip(hypot(x,y));
			float a = al::wrap(atan2(y,x)/M_2PI);

			Color col = HSV(a,1,m);

			int idx = j*Nx + i;
			int stride = tex.numComponents();
			pixels[idx*stride + 0] = col.r * 255.;
			pixels[idx*stride + 1] = col.g * 255.;
			pixels[idx*stride + 2] = col.b * 255.;
			pixels[idx*stride + 3] = col.a;
		}}

		// Generate the geometry onto which to display the texture
		mesh.primitive(Graphics::TRIANGLE_STRIP);
		mesh.vertex(-1,  1);
		mesh.vertex(-1, -1);
		mesh.vertex( 1,  1);
		mesh.vertex( 1, -1);

		// Add texture coordinates
		mesh.texCoord(0,1);
		mesh.texCoord(0,0);
		mesh.texCoord(1,1);
		mesh.texCoord(1,0);

		// The color acts as a multiplier on the texture color
		mesh.color(RGB(1)); // white: shows texture as is
		//mesh.color(RGB(1,0,0)); // red: shows only red components

		nav().pullBack(4);
		initWindow();
	}

	void onDraw(Graphics& g){
		// We must tell the GPU to use the texture when rendering primitives
		tex.bind();
			g.draw(mesh);
		tex.unbind();
	}
};

int main(){
	MyApp().start();
}
<|endoftext|>


<commit_before>#include "config.h"
#include "vm.hpp"
#include "state.hpp"
#include "on_stack.hpp"
#include "memory.hpp"
#include "call_frame.hpp"
#include "metrics.hpp"
#include "exception_point.hpp"
#include "thread_phase.hpp"

#include "builtin/array.hpp"
#include "builtin/class.hpp"
#include "builtin/module.hpp"
#include "builtin/thread.hpp"
#include "builtin/native_method.hpp"
#include "builtin/call_site.hpp"

#include "capi/handle.hpp"

#include "memory/finalizer.hpp"

#include "logger.hpp"

#include "dtrace/dtrace.h"

namespace rubinius {
  namespace memory {
    void NativeFinalizer::finalize(STATE) {
      (*finalizer_)(state, object());
    }

    void NativeFinalizer::mark(ImmixGC* gc) {
      if(Object* fwd = gc->saw_object(object())) {
        object(fwd);
      }
    }

    void ExtensionFinalizer::finalize(STATE) {
      ManagedPhase managed(state);

      NativeMethodEnvironment* env = state->vm()->native_method_environment;
      NativeMethodFrame nmf(env, 0, 0);
      ExceptionPoint ep(env);

      CallFrame* previous_frame = 0;
      CallFrame* call_frame = ALLOCA_CALL_FRAME(0);

      call_frame->previous = NULL;
      call_frame->constant_scope_ = 0;
      call_frame->dispatch_data = (void*)&nmf;
      call_frame->compiled_code = 0;
      call_frame->flags = CallFrame::cNativeMethod;
      call_frame->top_scope_ = 0;
      call_frame->scope = 0;
      call_frame->arguments = 0;

      env->set_current_call_frame(0);
      env->set_current_native_frame(&nmf);

      // Register the CallFrame, because we might GC below this.
      if(state->vm()->push_call_frame(state, call_frame, previous_frame)) {
        nmf.setup(Qnil, Qnil, Qnil, Qnil);

        PLACE_EXCEPTION_POINT(ep);

        if(unlikely(ep.jumped_to())) {
          logger::warn(
              "finalizer: an exception occurred running a NativeMethod finalizer");
        } else {
          (*finalizer_)(state, object());
        }

        state->vm()->pop_call_frame(state, previous_frame);
        env->set_current_call_frame(0);
        env->set_current_native_frame(0);
      } else {
        logger::warn("finalizer: stack error");
      }
    }

    void ExtensionFinalizer::mark(ImmixGC* gc) {
      if(Object* fwd = gc->saw_object(object())) {
        object(fwd);
      }
    }

    void ManagedFinalizer::finalize(STATE) {
      ManagedPhase managed(state);

      /* Rubinius specific code. If the finalizer is cTrue, then send the
       * object the __finalize__ message.
       */
      if(finalizer_->true_p()) {
        object()->send(state, state->symbol("__finalize__"));
      } else {
        Array* ary = Array::create(state, 1);
        ary->set(state, 0, object()->id(state));
        if(!finalizer_->send(state, G(sym_call), ary)) {
          if(state->vm()->thread_state()->raise_reason() == cException) {
            logger::warn(
                "finalizer: an exception occurred running a Ruby finalizer: %s",
                state->vm()->thread_state()->current_exception()->message_c_str(state));
          }
        }
      }
    }

    void ManagedFinalizer::mark(ImmixGC* gc) {
      if(Object* fwd = gc->saw_object(finalizer_)) {
        finalizer_ = fwd;
      }

      if(Object* fwd = gc->saw_object(object())) {
        object(fwd);
      }
    }

    bool ManagedFinalizer::match_p(STATE, Object* object, Object* finalizer) {
      bool match = false;

      if(this->object() == object) {
        if(!finalizer->nil_p()) {
          Array* args = Array::create(state, 1);
          args->set(state, 0, finalizer_);

          Object* result = finalizer->send(state, G(sym_equal), args);
          match = result && CBOOL(result);
        }
      }

      return match;
    }

    FinalizerThread::FinalizerThread(STATE)
      : MachineThread(state, "rbx.finalizer", MachineThread::eLarge)
      , live_list_()
      , process_list_()
      , synchronization_(NULL)
      , finishing_(false)
    {
      initialize(state);
      state->shared().set_finalizer(this);
    }

    FinalizerThread::~FinalizerThread() {
      if(!live_list_.empty()) {
        rubinius::bug("FinalizerThread destructed with remaining finalizer objects");
      }

      if(!process_list_.empty()) {
        rubinius::bug("FinalizerThread destructed with remaining to-be-finalized objects");
      }

      cleanup();
    }

    void FinalizerThread::cleanup() {
      if(synchronization_) {
        delete synchronization_;
        synchronization_ = NULL;
      }
    }

    void FinalizerThread::after_fork_child(STATE) {
      cleanup();

      MachineThread::after_fork_child(state);
    }

    void FinalizerThread::initialize(STATE) {
      synchronization_ = new Synchronization();
    }

    void FinalizerThread::wakeup(STATE) {
      MachineThread::wakeup(state);

      while(thread_running_) {
        synchronization_->list_condition().notify_one();
      }
    }

    void FinalizerThread::stop(STATE) {
      state->shared().machine_threads()->unregister_thread(this);

      stop_thread(state);
    }

    void FinalizerThread::run(STATE) {
      state->vm()->managed_phase();

      while(true) {
        FinalizerObject* object = 0;

        {
          std::unique_lock<std::mutex> lk(synchronization_->list_mutex());

          while(!thread_exit_ && process_list_.empty()) {
            UnmanagedPhase unmanaged(state);
            synchronization_->list_condition().wait(lk);
          }

          if(thread_exit_) return;

          if(!process_list_.empty()) {
            object = process_list_.back();
            process_list_.pop_back();
          }
        }

        state->vm()->thread_nexus()->yield(state->vm());

        if(object) {
          object->finalize(state);
          delete object;

          vm()->metrics().gc.objects_finalized++;
        }
      }
    }

    void FinalizerThread::finish(STATE) {
      finishing_ = true;

      // TODO: cleanup
      while(!process_list_.empty()) {
        FinalizerObject* fo = process_list_.back();
        process_list_.pop_back();

        fo->finalize(state);
        delete fo;

        vm()->metrics().gc.objects_finalized++;
      }

      while(!live_list_.empty()) {
        FinalizerObject* fo = live_list_.back();
        live_list_.pop_back();

        fo->finalize(state);
        delete fo;

        vm()->metrics().gc.objects_finalized++;
      }
    }

    void FinalizerThread::native_finalizer(STATE, Object* obj, FinalizerFunction func) {
      if(finishing_) return;

      add_finalizer(state, new NativeFinalizer(state, obj, func));
    }

    void FinalizerThread::extension_finalizer(STATE, Object* obj, FinalizerFunction func) {
      if(finishing_) return;

      add_finalizer(state, new ExtensionFinalizer(state, obj, func));
    }

    void FinalizerThread::managed_finalizer(STATE, Object* obj, Object* finalizer) {
      if(finishing_) return;

      {
        std::lock_guard<std::mutex> guard(synchronization_->list_mutex());

        for(FinalizerObjects::iterator i = live_list_.begin();
            i != live_list_.end();
            ++i)
        {
          FinalizerObject* fo = *i;

          /* TODO: Since Ruby allows any number of finalizers on a single
           * object as long as the finalizer "callable" is different, we have
           * to do a complex comparison to determine if the "callable" is
           * different. This results in a method send, which can cause a
           * CompiledCode instance to be internalized, adding CallSite object
           * finalizers, so we cannot keep this locked across this call.
           *
           * This is an utter mess and either needs to be moved into the Ruby
           * .define_finalizer method or locking handled differently on this
           * list.
           */
          synchronization_->list_mutex().unlock();

          if(fo->match_p(state, obj, finalizer)) {
            if(finalizer->nil_p()) {
              live_list_.erase(i);
            } else {
              synchronization_->list_mutex().lock();
              return;
            }
          }

          synchronization_->list_mutex().lock();
        }
      }

      /* Rubinius specific API. If the finalizer is the object, we're going to
       * send the object __finalize__. We mark that the user wants this by
       * putting cTrue as the ruby_finalizer.
       */
      add_finalizer(state, new ManagedFinalizer(state, obj,
            obj == finalizer ? cTrue : finalizer));
    }

    void FinalizerThread::add_finalizer(STATE, FinalizerObject* obj) {
      std::lock_guard<std::mutex> guard(synchronization_->list_mutex());

      live_list_.push_back(obj);
      vm()->metrics().gc.objects_queued++;
    }

    void FinalizerThread::gc_scan(ImmixGC* gc, Memory* memory) {
      for(FinalizerObjects::iterator i = live_list_.begin();
          i != live_list_.end();
          /* advance is handled in the loop */)
      {
        FinalizerObject* fo = *i;

        if(!fo->object()->marked_p(memory->mark())) {
          process_list_.push_back(*i);
          i = live_list_.erase(i);
        } else {
          ++i;
        }
      }

      for(FinalizerObjects::iterator i = process_list_.begin();
          i != process_list_.end();
          ++i)
      {
        FinalizerObject* fo = *i;

        fo->mark(gc);
      }

      synchronization_->list_condition().notify_one();
    }
  }
}
<commit_msg>Fixed removing a finalizer.<commit_after>#include "config.h"
#include "vm.hpp"
#include "state.hpp"
#include "on_stack.hpp"
#include "memory.hpp"
#include "call_frame.hpp"
#include "metrics.hpp"
#include "exception_point.hpp"
#include "thread_phase.hpp"

#include "builtin/array.hpp"
#include "builtin/class.hpp"
#include "builtin/module.hpp"
#include "builtin/thread.hpp"
#include "builtin/native_method.hpp"
#include "builtin/call_site.hpp"

#include "capi/handle.hpp"

#include "memory/finalizer.hpp"

#include "logger.hpp"

#include "dtrace/dtrace.h"

namespace rubinius {
  namespace memory {
    void NativeFinalizer::finalize(STATE) {
      (*finalizer_)(state, object());
    }

    void NativeFinalizer::mark(ImmixGC* gc) {
      if(Object* fwd = gc->saw_object(object())) {
        object(fwd);
      }
    }

    void ExtensionFinalizer::finalize(STATE) {
      ManagedPhase managed(state);

      NativeMethodEnvironment* env = state->vm()->native_method_environment;
      NativeMethodFrame nmf(env, 0, 0);
      ExceptionPoint ep(env);

      CallFrame* previous_frame = 0;
      CallFrame* call_frame = ALLOCA_CALL_FRAME(0);

      call_frame->previous = NULL;
      call_frame->constant_scope_ = 0;
      call_frame->dispatch_data = (void*)&nmf;
      call_frame->compiled_code = 0;
      call_frame->flags = CallFrame::cNativeMethod;
      call_frame->top_scope_ = 0;
      call_frame->scope = 0;
      call_frame->arguments = 0;

      env->set_current_call_frame(0);
      env->set_current_native_frame(&nmf);

      // Register the CallFrame, because we might GC below this.
      if(state->vm()->push_call_frame(state, call_frame, previous_frame)) {
        nmf.setup(Qnil, Qnil, Qnil, Qnil);

        PLACE_EXCEPTION_POINT(ep);

        if(unlikely(ep.jumped_to())) {
          logger::warn(
              "finalizer: an exception occurred running a NativeMethod finalizer");
        } else {
          (*finalizer_)(state, object());
        }

        state->vm()->pop_call_frame(state, previous_frame);
        env->set_current_call_frame(0);
        env->set_current_native_frame(0);
      } else {
        logger::warn("finalizer: stack error");
      }
    }

    void ExtensionFinalizer::mark(ImmixGC* gc) {
      if(Object* fwd = gc->saw_object(object())) {
        object(fwd);
      }
    }

    void ManagedFinalizer::finalize(STATE) {
      ManagedPhase managed(state);

      /* Rubinius specific code. If the finalizer is cTrue, then send the
       * object the __finalize__ message.
       */
      if(finalizer_->true_p()) {
        object()->send(state, state->symbol("__finalize__"));
      } else {
        Array* ary = Array::create(state, 1);
        ary->set(state, 0, object()->id(state));
        if(!finalizer_->send(state, G(sym_call), ary)) {
          if(state->vm()->thread_state()->raise_reason() == cException) {
            logger::warn(
                "finalizer: an exception occurred running a Ruby finalizer: %s",
                state->vm()->thread_state()->current_exception()->message_c_str(state));
          }
        }
      }
    }

    void ManagedFinalizer::mark(ImmixGC* gc) {
      if(Object* fwd = gc->saw_object(finalizer_)) {
        finalizer_ = fwd;
      }

      if(Object* fwd = gc->saw_object(object())) {
        object(fwd);
      }
    }

    bool ManagedFinalizer::match_p(STATE, Object* object, Object* finalizer) {
      bool match = false;

      if(this->object() == object) {
        if(!finalizer->nil_p()) {
          Array* args = Array::create(state, 1);
          args->set(state, 0, finalizer_);

          Object* result = finalizer->send(state, G(sym_equal), args);
          match = result && CBOOL(result);
        }
      }

      return match;
    }

    FinalizerThread::FinalizerThread(STATE)
      : MachineThread(state, "rbx.finalizer", MachineThread::eLarge)
      , live_list_()
      , process_list_()
      , synchronization_(NULL)
      , finishing_(false)
    {
      initialize(state);
      state->shared().set_finalizer(this);
    }

    FinalizerThread::~FinalizerThread() {
      if(!live_list_.empty()) {
        rubinius::bug("FinalizerThread destructed with remaining finalizer objects");
      }

      if(!process_list_.empty()) {
        rubinius::bug("FinalizerThread destructed with remaining to-be-finalized objects");
      }

      cleanup();
    }

    void FinalizerThread::cleanup() {
      if(synchronization_) {
        delete synchronization_;
        synchronization_ = NULL;
      }
    }

    void FinalizerThread::after_fork_child(STATE) {
      cleanup();

      MachineThread::after_fork_child(state);
    }

    void FinalizerThread::initialize(STATE) {
      synchronization_ = new Synchronization();
    }

    void FinalizerThread::wakeup(STATE) {
      MachineThread::wakeup(state);

      while(thread_running_) {
        synchronization_->list_condition().notify_one();
      }
    }

    void FinalizerThread::stop(STATE) {
      state->shared().machine_threads()->unregister_thread(this);

      stop_thread(state);
    }

    void FinalizerThread::run(STATE) {
      state->vm()->managed_phase();

      while(true) {
        FinalizerObject* object = 0;

        {
          std::unique_lock<std::mutex> lk(synchronization_->list_mutex());

          while(!thread_exit_ && process_list_.empty()) {
            UnmanagedPhase unmanaged(state);
            synchronization_->list_condition().wait(lk);
          }

          if(thread_exit_) return;

          if(!process_list_.empty()) {
            object = process_list_.back();
            process_list_.pop_back();
          }
        }

        state->vm()->thread_nexus()->yield(state->vm());

        if(object) {
          object->finalize(state);
          delete object;

          vm()->metrics().gc.objects_finalized++;
        }
      }
    }

    void FinalizerThread::finish(STATE) {
      finishing_ = true;

      // TODO: cleanup
      while(!process_list_.empty()) {
        FinalizerObject* fo = process_list_.back();
        process_list_.pop_back();

        fo->finalize(state);
        delete fo;

        vm()->metrics().gc.objects_finalized++;
      }

      while(!live_list_.empty()) {
        FinalizerObject* fo = live_list_.back();
        live_list_.pop_back();

        fo->finalize(state);
        delete fo;

        vm()->metrics().gc.objects_finalized++;
      }
    }

    void FinalizerThread::native_finalizer(STATE, Object* obj, FinalizerFunction func) {
      if(finishing_) return;

      add_finalizer(state, new NativeFinalizer(state, obj, func));
    }

    void FinalizerThread::extension_finalizer(STATE, Object* obj, FinalizerFunction func) {
      if(finishing_) return;

      add_finalizer(state, new ExtensionFinalizer(state, obj, func));
    }

    void FinalizerThread::managed_finalizer(STATE, Object* obj, Object* finalizer) {
      if(finishing_) return;

      {
        std::lock_guard<std::mutex> guard(synchronization_->list_mutex());

        for(FinalizerObjects::iterator i = live_list_.begin();
            i != live_list_.end();
            /* advance is handled in the loop */)
        {
          FinalizerObject* fo = *i;

          /* TODO: Since Ruby allows any number of finalizers on a single
           * object as long as the finalizer "callable" is different, we have
           * to do a complex comparison to determine if the "callable" is
           * different. This results in a method send, which can cause a
           * CompiledCode instance to be internalized, adding CallSite object
           * finalizers, so we cannot keep this locked across this call.
           *
           * This is an utter mess and either needs to be moved into the Ruby
           * .define_finalizer method or locking handled differently on this
           * list.
           */
          synchronization_->list_mutex().unlock();

          if(fo->match_p(state, obj, finalizer)) {
            if(finalizer->nil_p()) {
              i = live_list_.erase(i);
              continue;
            } else {
              synchronization_->list_mutex().lock();
              return;
            }
          }

          synchronization_->list_mutex().lock();
          ++i;
        }
      }

      if(finalizer->nil_p()) return;

      /* Rubinius specific API. If the finalizer is the object, we're going to
       * send the object __finalize__. We mark that the user wants this by
       * putting cTrue as the ruby_finalizer.
       */
      add_finalizer(state, new ManagedFinalizer(state, obj,
            obj == finalizer ? cTrue : finalizer));
    }

    void FinalizerThread::add_finalizer(STATE, FinalizerObject* obj) {
      std::lock_guard<std::mutex> guard(synchronization_->list_mutex());

      live_list_.push_back(obj);
      vm()->metrics().gc.objects_queued++;
    }

    void FinalizerThread::gc_scan(ImmixGC* gc, Memory* memory) {
      for(FinalizerObjects::iterator i = live_list_.begin();
          i != live_list_.end();
          /* advance is handled in the loop */)
      {
        FinalizerObject* fo = *i;

        if(!fo->object()->marked_p(memory->mark())) {
          process_list_.push_back(*i);
          i = live_list_.erase(i);
        } else {
          ++i;
        }
      }

      for(FinalizerObjects::iterator i = process_list_.begin();
          i != process_list_.end();
          ++i)
      {
        FinalizerObject* fo = *i;

        fo->mark(gc);
      }

      synchronization_->list_condition().notify_one();
    }
  }
}
<|endoftext|>


<commit_before>/*
 *
 */

#include <iostream>
#include <string>
using namespace std;

string to_lowercase (string in);

int main()
{
	string name;

	do
	{
		int sum = 0;
		cout << "Enter name: ";
		cin >> name;
		name = to_lowercase(name);
		for (int i = 0; name[i]; i++)
		{
			sum += (int)(name[i] - 'a' + 1);
		}
		if (sum % name.length())
		{
			cout << name << ": No" << endl;
		}
		else
		{
			cout << name << ": Yes" << endl;
		}
	} while (name != "0");

	return 0;
}

string to_lowercase (string in)
{
	for (int i = 0; in[i]; i++)
	{
		if(in[i] <= 'Z' && in[i] >= 'A')
		{
			in[i] = in[i] - ('Z' - 'z');
		}
	}
	return in;
}
<commit_msg>new lines to seperate chuncks of code<commit_after>/*
 *
 */

#include <iostream>
#include <string>
using namespace std;

string to_lowercase (string in);

int main()
{
	string name;

	do
	{
		int sum = 0;
		cout << "Enter name: ";
		cin >> name;
		name = to_lowercase(name);

		for (int i = 0; name[i]; i++)
		{
			sum += (int)(name[i] - 'a' + 1);
		}
		if (sum % name.length())
		{
			cout << name << ": No" << endl;
		}
		else
		{
			cout << name << ": Yes" << endl;
		}
	} while (name != "0");

	return 0;
}

string to_lowercase (string in)
{
	for (int i = 0; in[i]; i++)
	{
		if(in[i] <= 'Z' && in[i] >= 'A')
		{
			in[i] = in[i] - ('Z' - 'z');
		}
	}
	return in;
}
<|endoftext|>