<commit_before>// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include <string>
#include "atom/browser/api/atom_api_session.h"
#include "atom/browser/api/atom_api_url_request.h"
#include "atom/browser/net/atom_url_request.h"
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/net_converter.h"
#include "atom/common/native_mate_converters/string16_converter.h"
#include "atom/common/node_includes.h"
#include "native_mate/dictionary.h"

namespace mate {

template<>
struct Converter<scoped_refptr<const net::HttpResponseHeaders>> {
  static v8::Local<v8::Value> ToV8(
    v8::Isolate* isolate,
    scoped_refptr<const net::HttpResponseHeaders> val) {
    mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
    if (val) {
      size_t iter = 0;
      std::string name;
      std::string value;
      while (val->EnumerateHeaderLines(&iter, &name, &value)) {
        dict.Set(name, value);
      }
    }
    return dict.GetHandle();
  }
};

template<>
struct Converter<scoped_refptr<const net::IOBufferWithSize>> {
  static v8::Local<v8::Value> ToV8(
    v8::Isolate* isolate,
    scoped_refptr<const net::IOBufferWithSize> buffer) {
    return node::Buffer::Copy(isolate,
      buffer->data(),
      buffer->size()).ToLocalChecked();
  }

  static bool FromV8(
    v8::Isolate* isolate,
    v8::Local<v8::Value> val,
    scoped_refptr<const net::IOBufferWithSize>* out) {
    auto size = node::Buffer::Length(val);

    if (size == 0) {
      // Support conversion from empty buffer. A use case is
      // a GET request without body.
      // Since zero-sized IOBuffer(s) are not supported, we set the
      // out pointer to null.
      *out = nullptr;
      return true;
    }
    auto data = node::Buffer::Data(val);
    if (!data) {
      // This is an error as size is positive but data is null.
      return false;
    }

    auto io_buffer = new net::IOBufferWithSize(size);
    if (!io_buffer) {
      // Assuming allocation failed.
      return false;
    }

    // We do a deep copy. We could have used Buffer's internal memory
    // but that is much more complicated to be properly handled.
    memcpy(io_buffer->data(), data, size);
    *out = io_buffer;
    return true;
  }
};

}  // namespace mate

namespace atom {
namespace api {

template <typename Flags>
URLRequest::StateBase<Flags>::StateBase(Flags initialState)
  : state_(initialState) {
}

template <typename Flags>
void URLRequest::StateBase<Flags>::SetFlag(Flags flag) {
  state_ = static_cast<Flags>(static_cast<int>(state_) &
    static_cast<int>(flag));
}

template <typename Flags>
bool URLRequest::StateBase<Flags>::operator==(Flags flag) const {
  return state_ == flag;
}

template <typename Flags>
bool URLRequest::StateBase<Flags>::IsFlagSet(Flags flag) const {
  return static_cast<int>(state_) & static_cast<int>(flag);
}

URLRequest::RequestState::RequestState()
  : StateBase(RequestStateFlags::kNotStarted) {
}

bool URLRequest::RequestState::NotStarted() const {
  return *this == RequestStateFlags::kNotStarted;
}

bool URLRequest::RequestState::Started() const {
  return IsFlagSet(RequestStateFlags::kStarted);
}

bool URLRequest::RequestState::Finished() const {
  return IsFlagSet(RequestStateFlags::kFinished);
}

bool URLRequest::RequestState::Canceled() const {
  return IsFlagSet(RequestStateFlags::kCanceled);
}

bool URLRequest::RequestState::Failed() const {
  return IsFlagSet(RequestStateFlags::kFailed);
}

bool URLRequest::RequestState::Closed() const {
  return IsFlagSet(RequestStateFlags::kClosed);
}

URLRequest::ResponseState::ResponseState()
  : StateBase(ResponseStateFlags::kNotStarted) {
}

bool URLRequest::ResponseState::NotStarted() const {
  return *this == ResponseStateFlags::kNotStarted;
}

bool URLRequest::ResponseState::Started() const {
  return IsFlagSet(ResponseStateFlags::kStarted);
}

bool URLRequest::ResponseState::Ended() const {
  return IsFlagSet(ResponseStateFlags::kEnded);
}

bool URLRequest::ResponseState::Failed() const {
  return IsFlagSet(ResponseStateFlags::kFailed);
}

URLRequest::URLRequest(v8::Isolate* isolate, v8::Local<v8::Object> wrapper)
    : weak_ptr_factory_(this) {
  InitWith(isolate, wrapper);
}

URLRequest::~URLRequest() {
}

// static
mate::WrappableBase* URLRequest::New(mate::Arguments* args) {
  v8::Local<v8::Object> options;
  args->GetNext(&options);
  mate::Dictionary dict(args->isolate(), options);
  std::string method;
  dict.Get("method", &method);
  std::string url;
  dict.Get("url", &url);
  std::string session_name;
  dict.Get("session", &session_name);

  auto session = Session::FromPartition(args->isolate(), session_name);

  auto browser_context = session->browser_context();
  auto api_url_request = new URLRequest(args->isolate(), args->GetThis());
  auto weak_ptr = api_url_request->weak_ptr_factory_.GetWeakPtr();
  auto atom_url_request = AtomURLRequest::Create(
    browser_context,
    method,
    url,
    weak_ptr);

  api_url_request->atom_request_ = atom_url_request;

  return api_url_request;
}

// static
void URLRequest::BuildPrototype(v8::Isolate* isolate,
                                v8::Local<v8::FunctionTemplate> prototype) {
  prototype->SetClassName(mate::StringToV8(isolate, "URLRequest"));
  mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
    // Request API
    .MakeDestroyable()
    .SetMethod("write", &URLRequest::Write)
    .SetMethod("cancel", &URLRequest::Cancel)
    .SetMethod("setExtraHeader", &URLRequest::SetExtraHeader)
    .SetMethod("removeExtraHeader", &URLRequest::RemoveExtraHeader)
    .SetMethod("setChunkedUpload", &URLRequest::SetChunkedUpload)
    .SetProperty("notStarted", &URLRequest::NotStarted)
    .SetProperty("finished", &URLRequest::Finished)
    // Response APi
    .SetProperty("statusCode", &URLRequest::StatusCode)
    .SetProperty("statusMessage", &URLRequest::StatusMessage)
    .SetProperty("rawResponseHeaders", &URLRequest::RawResponseHeaders)
    .SetProperty("httpVersionMajor", &URLRequest::ResponseHttpVersionMajor)
    .SetProperty("httpVersionMinor", &URLRequest::ResponseHttpVersionMinor);
}

bool URLRequest::NotStarted() const {
  return request_state_.NotStarted();
}

bool URLRequest::Finished() const {
  return request_state_.Finished();
}

bool URLRequest::Canceled() const {
  return request_state_.Canceled();
}

bool URLRequest::Write(
    scoped_refptr<const net::IOBufferWithSize> buffer,
    bool is_last) {
  if (request_state_.Canceled() ||
    request_state_.Failed() ||
    request_state_.Finished() ||
    request_state_.Closed()) {
    return false;
  }

  if (request_state_.NotStarted()) {
    request_state_.SetFlag(RequestStateFlags::kStarted);
    // Pin on first write.
    pin();
  }

  if (is_last) {
    request_state_.SetFlag(RequestStateFlags::kFinished);
    EmitRequestEvent(true, "finish");
  }

  DCHECK(atom_request_);
  if (atom_request_) {
    return atom_request_->Write(buffer, is_last);
  }
  return false;
}

void URLRequest::Cancel() {
  if (request_state_.Canceled() ||
      request_state_.Closed()) {
    // Cancel only once.
    return;
  }

  // Mark as canceled.
  request_state_.SetFlag(RequestStateFlags::kCanceled);

  DCHECK(atom_request_);
  if (atom_request_ && request_state_.Started()) {
    // Really cancel if it was started.
    atom_request_->Cancel();
  }
  EmitRequestEvent(true, "abort");

  if (response_state_.Started() && !response_state_.Ended()) {
    EmitResponseEvent(true, "aborted");
  }
  Close();
}

bool URLRequest::SetExtraHeader(const std::string& name,
                           const std::string& value) {
  // State must be equal to not started.
  if (!request_state_.NotStarted()) {
    // Cannot change headers after send.
    return false;
  }

  if (!net::HttpUtil::IsValidHeaderName(name)) {
    return false;
  }

  if (!net::HttpUtil::IsValidHeaderValue(value)) {
    return false;
  }

  atom_request_->SetExtraHeader(name, value);
  return true;
}

void URLRequest::RemoveExtraHeader(const std::string& name) {
  // State must be equal to not started.
  if (!request_state_.NotStarted()) {
    // Cannot change headers after send.
    return;
  }
  atom_request_->RemoveExtraHeader(name);
}

void URLRequest::SetChunkedUpload(bool is_chunked_upload) {
  // State must be equal to not started.
  if (!request_state_.NotStarted()) {
    // Cannot change headers after send.
    return;
  }
  atom_request_->SetChunkedUpload(is_chunked_upload);
}

void URLRequest::OnAuthenticationRequired(
    scoped_refptr<const net::AuthChallengeInfo> auth_info) {
  EmitRequestEvent(
    false,
    "login",
    auth_info.get(),
    base::Bind(&AtomURLRequest::PassLoginInformation, atom_request_));
}

void URLRequest::OnResponseStarted(
    scoped_refptr<const net::HttpResponseHeaders> response_headers) {
  if (request_state_.Canceled() ||
      request_state_.Failed() ||
      request_state_.Closed()) {
    // Don't emit any event after request cancel.
    return;
  }
  response_headers_ = response_headers;
  response_state_.SetFlag(ResponseStateFlags::kStarted);
  Emit("response");
}

void URLRequest::OnResponseData(
    scoped_refptr<const net::IOBufferWithSize> buffer) {
  if (request_state_.Canceled() ||
      request_state_.Closed() ||
      request_state_.Failed() ||
      response_state_.Failed()) {
    // In case we received an unexpected event from Chromium net,
    // don't emit any data event after request cancel/error/close.
    return;
  }
  if (!buffer || !buffer->data() || !buffer->size()) {
    return;
  }
  EmitResponseEvent(false, "data", buffer);
}

void URLRequest::OnResponseCompleted() {
  if (request_state_.Canceled() ||
    request_state_.Closed() ||
    request_state_.Failed() ||
    response_state_.Failed()) {
    // In case we received an unexpected event from Chromium net,
    // don't emit any data event after request cancel/error/close.
    return;
  }
  response_state_.SetFlag(ResponseStateFlags::kEnded);
  EmitResponseEvent(false, "end");
  Close();
}

void URLRequest::OnRequestError(const std::string& error) {
  request_state_.SetFlag(RequestStateFlags::kFailed);
  auto error_object = v8::Exception::Error(mate::StringToV8(isolate(), error));
  EmitRequestEvent(false, "error", error_object);
  Close();
}

void URLRequest::OnResponseError(const std::string& error) {
  response_state_.SetFlag(ResponseStateFlags::kFailed);
  auto error_object = v8::Exception::Error(mate::StringToV8(isolate(), error));
  EmitResponseEvent(false, "error", error_object);
  Close();
}

int URLRequest::StatusCode() const {
  if (response_headers_) {
    return response_headers_->response_code();
  }
  return -1;
}

std::string URLRequest::StatusMessage() const {
  std::string result;
  if (response_headers_) {
    result = response_headers_->GetStatusText();
  }
  return result;
}

scoped_refptr<const net::HttpResponseHeaders>
URLRequest::RawResponseHeaders() const {
  return response_headers_;
}

uint32_t URLRequest::ResponseHttpVersionMajor() const {
  if (response_headers_) {
     return response_headers_->GetHttpVersion().major_value();
  }
  return 0;
}

uint32_t URLRequest::ResponseHttpVersionMinor() const {
  if (response_headers_) {
    return response_headers_->GetHttpVersion().minor_value();
  }
  return 0;
}

void URLRequest::Close() {
  if (!request_state_.Closed()) {
    request_state_.SetFlag(RequestStateFlags::kClosed);
    if (response_state_.Started()) {
      // Emit a close event if we really have a response object.
      EmitResponseEvent(true, "close");
    }
    EmitRequestEvent(true, "close");
  }
  unpin();
  atom_request_ = nullptr;
}

void URLRequest::pin() {
  if (wrapper_.IsEmpty()) {
    wrapper_.Reset(isolate(), GetWrapper());
  }
}

void URLRequest::unpin() {
  wrapper_.Reset();
}

}  // namespace api

}  // namespace atom
<commit_msg>Adding systematic checks on the atom_request_ pointer as it may be reset to null.<commit_after>// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include <string>
#include "atom/browser/api/atom_api_session.h"
#include "atom/browser/api/atom_api_url_request.h"
#include "atom/browser/net/atom_url_request.h"
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/net_converter.h"
#include "atom/common/native_mate_converters/string16_converter.h"
#include "atom/common/node_includes.h"
#include "native_mate/dictionary.h"

namespace mate {

template<>
struct Converter<scoped_refptr<const net::HttpResponseHeaders>> {
  static v8::Local<v8::Value> ToV8(
    v8::Isolate* isolate,
    scoped_refptr<const net::HttpResponseHeaders> val) {
    mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
    if (val) {
      size_t iter = 0;
      std::string name;
      std::string value;
      while (val->EnumerateHeaderLines(&iter, &name, &value)) {
        dict.Set(name, value);
      }
    }
    return dict.GetHandle();
  }
};

template<>
struct Converter<scoped_refptr<const net::IOBufferWithSize>> {
  static v8::Local<v8::Value> ToV8(
    v8::Isolate* isolate,
    scoped_refptr<const net::IOBufferWithSize> buffer) {
    return node::Buffer::Copy(isolate,
      buffer->data(),
      buffer->size()).ToLocalChecked();
  }

  static bool FromV8(
    v8::Isolate* isolate,
    v8::Local<v8::Value> val,
    scoped_refptr<const net::IOBufferWithSize>* out) {
    auto size = node::Buffer::Length(val);

    if (size == 0) {
      // Support conversion from empty buffer. A use case is
      // a GET request without body.
      // Since zero-sized IOBuffer(s) are not supported, we set the
      // out pointer to null.
      *out = nullptr;
      return true;
    }
    auto data = node::Buffer::Data(val);
    if (!data) {
      // This is an error as size is positive but data is null.
      return false;
    }

    auto io_buffer = new net::IOBufferWithSize(size);
    if (!io_buffer) {
      // Assuming allocation failed.
      return false;
    }

    // We do a deep copy. We could have used Buffer's internal memory
    // but that is much more complicated to be properly handled.
    memcpy(io_buffer->data(), data, size);
    *out = io_buffer;
    return true;
  }
};

}  // namespace mate

namespace atom {
namespace api {

template <typename Flags>
URLRequest::StateBase<Flags>::StateBase(Flags initialState)
  : state_(initialState) {
}

template <typename Flags>
void URLRequest::StateBase<Flags>::SetFlag(Flags flag) {
  state_ = static_cast<Flags>(static_cast<int>(state_) &
    static_cast<int>(flag));
}

template <typename Flags>
bool URLRequest::StateBase<Flags>::operator==(Flags flag) const {
  return state_ == flag;
}

template <typename Flags>
bool URLRequest::StateBase<Flags>::IsFlagSet(Flags flag) const {
  return static_cast<int>(state_) & static_cast<int>(flag);
}

URLRequest::RequestState::RequestState()
  : StateBase(RequestStateFlags::kNotStarted) {
}

bool URLRequest::RequestState::NotStarted() const {
  return *this == RequestStateFlags::kNotStarted;
}

bool URLRequest::RequestState::Started() const {
  return IsFlagSet(RequestStateFlags::kStarted);
}

bool URLRequest::RequestState::Finished() const {
  return IsFlagSet(RequestStateFlags::kFinished);
}

bool URLRequest::RequestState::Canceled() const {
  return IsFlagSet(RequestStateFlags::kCanceled);
}

bool URLRequest::RequestState::Failed() const {
  return IsFlagSet(RequestStateFlags::kFailed);
}

bool URLRequest::RequestState::Closed() const {
  return IsFlagSet(RequestStateFlags::kClosed);
}

URLRequest::ResponseState::ResponseState()
  : StateBase(ResponseStateFlags::kNotStarted) {
}

bool URLRequest::ResponseState::NotStarted() const {
  return *this == ResponseStateFlags::kNotStarted;
}

bool URLRequest::ResponseState::Started() const {
  return IsFlagSet(ResponseStateFlags::kStarted);
}

bool URLRequest::ResponseState::Ended() const {
  return IsFlagSet(ResponseStateFlags::kEnded);
}

bool URLRequest::ResponseState::Failed() const {
  return IsFlagSet(ResponseStateFlags::kFailed);
}

URLRequest::URLRequest(v8::Isolate* isolate, v8::Local<v8::Object> wrapper)
    : weak_ptr_factory_(this) {
  InitWith(isolate, wrapper);
}

URLRequest::~URLRequest() {
}

// static
mate::WrappableBase* URLRequest::New(mate::Arguments* args) {
  v8::Local<v8::Object> options;
  args->GetNext(&options);
  mate::Dictionary dict(args->isolate(), options);
  std::string method;
  dict.Get("method", &method);
  std::string url;
  dict.Get("url", &url);
  std::string session_name;
  dict.Get("session", &session_name);

  auto session = Session::FromPartition(args->isolate(), session_name);

  auto browser_context = session->browser_context();
  auto api_url_request = new URLRequest(args->isolate(), args->GetThis());
  auto weak_ptr = api_url_request->weak_ptr_factory_.GetWeakPtr();
  auto atom_url_request = AtomURLRequest::Create(
    browser_context,
    method,
    url,
    weak_ptr);

  api_url_request->atom_request_ = atom_url_request;

  return api_url_request;
}

// static
void URLRequest::BuildPrototype(v8::Isolate* isolate,
                                v8::Local<v8::FunctionTemplate> prototype) {
  prototype->SetClassName(mate::StringToV8(isolate, "URLRequest"));
  mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
    // Request API
    .MakeDestroyable()
    .SetMethod("write", &URLRequest::Write)
    .SetMethod("cancel", &URLRequest::Cancel)
    .SetMethod("setExtraHeader", &URLRequest::SetExtraHeader)
    .SetMethod("removeExtraHeader", &URLRequest::RemoveExtraHeader)
    .SetMethod("setChunkedUpload", &URLRequest::SetChunkedUpload)
    .SetProperty("notStarted", &URLRequest::NotStarted)
    .SetProperty("finished", &URLRequest::Finished)
    // Response APi
    .SetProperty("statusCode", &URLRequest::StatusCode)
    .SetProperty("statusMessage", &URLRequest::StatusMessage)
    .SetProperty("rawResponseHeaders", &URLRequest::RawResponseHeaders)
    .SetProperty("httpVersionMajor", &URLRequest::ResponseHttpVersionMajor)
    .SetProperty("httpVersionMinor", &URLRequest::ResponseHttpVersionMinor);
}

bool URLRequest::NotStarted() const {
  return request_state_.NotStarted();
}

bool URLRequest::Finished() const {
  return request_state_.Finished();
}

bool URLRequest::Canceled() const {
  return request_state_.Canceled();
}

bool URLRequest::Write(
    scoped_refptr<const net::IOBufferWithSize> buffer,
    bool is_last) {
  if (request_state_.Canceled() ||
    request_state_.Failed() ||
    request_state_.Finished() ||
    request_state_.Closed()) {
    return false;
  }

  if (request_state_.NotStarted()) {
    request_state_.SetFlag(RequestStateFlags::kStarted);
    // Pin on first write.
    pin();
  }

  if (is_last) {
    request_state_.SetFlag(RequestStateFlags::kFinished);
    EmitRequestEvent(true, "finish");
  }

  DCHECK(atom_request_);
  if (atom_request_) {
    return atom_request_->Write(buffer, is_last);
  }
  return false;
}

void URLRequest::Cancel() {
  if (request_state_.Canceled() ||
      request_state_.Closed()) {
    // Cancel only once.
    return;
  }

  // Mark as canceled.
  request_state_.SetFlag(RequestStateFlags::kCanceled);

  DCHECK(atom_request_);
  if (atom_request_ && request_state_.Started()) {
    // Really cancel if it was started.
    atom_request_->Cancel();
  }
  EmitRequestEvent(true, "abort");

  if (response_state_.Started() && !response_state_.Ended()) {
    EmitResponseEvent(true, "aborted");
  }
  Close();
}

bool URLRequest::SetExtraHeader(const std::string& name,
                           const std::string& value) {
  // Request state must be in the initial non started state.
  if (!request_state_.NotStarted()) {
    // Cannot change headers after send.
    return false;
  }

  if (!net::HttpUtil::IsValidHeaderName(name)) {
    return false;
  }

  if (!net::HttpUtil::IsValidHeaderValue(value)) {
    return false;
  }

  DCHECK(atom_request_);
  if (atom_request_) {
    atom_request_->SetExtraHeader(name, value);
  }
  return true;
}

void URLRequest::RemoveExtraHeader(const std::string& name) {
  // State must be equal to not started.
  if (!request_state_.NotStarted()) {
    // Cannot change headers after send.
    return;
  }
  DCHECK(atom_request_);
  if (atom_request_) {
    atom_request_->RemoveExtraHeader(name);
  }
}

void URLRequest::SetChunkedUpload(bool is_chunked_upload) {
  // State must be equal to not started.
  if (!request_state_.NotStarted()) {
    // Cannot change headers after send.
    return;
  }
  DCHECK(atom_request_);
  if (atom_request_) {
    atom_request_->SetChunkedUpload(is_chunked_upload);
  }
}

void URLRequest::OnAuthenticationRequired(
  scoped_refptr<const net::AuthChallengeInfo> auth_info) {
  if (request_state_.Canceled() ||
    request_state_.Closed()) {
    return;
  }

  DCHECK(atom_request_);
  if (!atom_request_) {
    return;
  }

  EmitRequestEvent(
    false,
    "login",
    auth_info.get(),
    base::Bind(&AtomURLRequest::PassLoginInformation, atom_request_));
}

void URLRequest::OnResponseStarted(
    scoped_refptr<const net::HttpResponseHeaders> response_headers) {
  if (request_state_.Canceled() ||
      request_state_.Failed() ||
      request_state_.Closed()) {
    // Don't emit any event after request cancel.
    return;
  }
  response_headers_ = response_headers;
  response_state_.SetFlag(ResponseStateFlags::kStarted);
  Emit("response");
}

void URLRequest::OnResponseData(
    scoped_refptr<const net::IOBufferWithSize> buffer) {
  if (request_state_.Canceled() ||
      request_state_.Closed() ||
      request_state_.Failed() ||
      response_state_.Failed()) {
    // In case we received an unexpected event from Chromium net,
    // don't emit any data event after request cancel/error/close.
    return;
  }
  if (!buffer || !buffer->data() || !buffer->size()) {
    return;
  }
  EmitResponseEvent(false, "data", buffer);
}

void URLRequest::OnResponseCompleted() {
  if (request_state_.Canceled() ||
    request_state_.Closed() ||
    request_state_.Failed() ||
    response_state_.Failed()) {
    // In case we received an unexpected event from Chromium net,
    // don't emit any data event after request cancel/error/close.
    return;
  }
  response_state_.SetFlag(ResponseStateFlags::kEnded);
  EmitResponseEvent(false, "end");
  Close();
}

void URLRequest::OnRequestError(const std::string& error) {
  auto error_object = v8::Exception::Error(mate::StringToV8(isolate(), error));
  request_state_.SetFlag(RequestStateFlags::kFailed);
  EmitRequestEvent(false, "error", error_object);
  Close();
}

void URLRequest::OnResponseError(const std::string& error) {
  auto error_object = v8::Exception::Error(mate::StringToV8(isolate(), error));
  response_state_.SetFlag(ResponseStateFlags::kFailed);
  EmitResponseEvent(false, "error", error_object);
  Close();
}

int URLRequest::StatusCode() const {
  if (response_headers_) {
    return response_headers_->response_code();
  }
  return -1;
}

std::string URLRequest::StatusMessage() const {
  std::string result;
  if (response_headers_) {
    result = response_headers_->GetStatusText();
  }
  return result;
}

scoped_refptr<const net::HttpResponseHeaders>
URLRequest::RawResponseHeaders() const {
  return response_headers_;
}

uint32_t URLRequest::ResponseHttpVersionMajor() const {
  if (response_headers_) {
     return response_headers_->GetHttpVersion().major_value();
  }
  return 0;
}

uint32_t URLRequest::ResponseHttpVersionMinor() const {
  if (response_headers_) {
    return response_headers_->GetHttpVersion().minor_value();
  }
  return 0;
}

void URLRequest::Close() {
  if (!request_state_.Closed()) {
    request_state_.SetFlag(RequestStateFlags::kClosed);
    if (response_state_.Started()) {
      // Emit a close event if we really have a response object.
      EmitResponseEvent(true, "close");
    }
    EmitRequestEvent(true, "close");
  }
  unpin();
  atom_request_ = nullptr;
}

void URLRequest::pin() {
  if (wrapper_.IsEmpty()) {
    wrapper_.Reset(isolate(), GetWrapper());
  }
}

void URLRequest::unpin() {
  wrapper_.Reset();
}

}  // namespace api

}  // namespace atom
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: parsenv2.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 18:46:39 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

#include <precomp.h>
#include <s2_luidl/parsenv2.hxx>

// NOT FULLY DEFINED SERVICES
#include <ary/ary.hxx>
#include <ary/qualiname.hxx>
#include <ary_i/codeinf2.hxx>
#include <ary/idl/i_gate.hxx>
#include <ary/idl/i_ce.hxx>
#include <ary/idl/i_enumvalue.hxx>
#include <ary/idl/ip_ce.hxx>
#include <parser/parserinfo.hxx>
#include <adc_msg.hxx>
#include <s2_luidl/uidl_tok.hxx>
#include <x_parse2.hxx>

namespace csi
{
namespace uidl
{

UnoIDL_PE::~UnoIDL_PE()
{
}

void
UnoIDL_PE::EstablishContacts( UnoIDL_PE *               io_pParentPE,
                              ary::n22::Repository &    io_rRepository,
                              TokenProcessing_Result &  o_rResult )
{
    aMyNode.EstablishContacts(io_pParentPE, io_rRepository.Gate_Idl(), o_rResult);
}

void
UnoIDL_PE::EstablishContacts( UnoIDL_PE *               io_pParentPE,
                              ary::idl::Gate &          io_rGate,
                              TokenProcessing_Result &  o_rResult )
{
    aMyNode.EstablishContacts(io_pParentPE, io_rGate, o_rResult);
}

void
UnoIDL_PE::Enter( E_EnvStackAction  i_eWayOfEntering )
{
    switch (i_eWayOfEntering)
    {
        case push_sure:
                InitData();
                break;
        case push_try:
                csv_assert(false);
                break;
        case pop_success:
                ReceiveData();
                break;
        case pop_failure:
                throw X_AutodocParser(X_AutodocParser::x_Any);
                break;
        default:
            csv_assert(false);
    }   // end switch
}

void
UnoIDL_PE::Leave( E_EnvStackAction  i_eWayOfLeaving )
{
    switch (i_eWayOfLeaving)
    {
        case push_sure:
                break;
        case push_try:
                csv_assert(false);
                break;
        case pop_success:
                TransferData();
                break;
        case pop_failure:
                throw X_AutodocParser(X_AutodocParser::x_Any);
                break;
        default:
            csv_assert(false);
    }   // end switch
}

void
UnoIDL_PE::SetDocu( DYN ary::info::CodeInformation * let_dpDocu )
{
    pDocu = let_dpDocu;
}

void
UnoIDL_PE::SetPublished()
{
    if (NOT pDocu)
    {
        pDocu = new ary::info::CodeInformation;
    }
    pDocu->SetPublished();
}

void
UnoIDL_PE::SetOptional()
{
    if (NOT pDocu)
    {
        pDocu = new ary::info::CodeInformation;
    }
    pDocu->SetOptional();
}

void
UnoIDL_PE::PassDocuAt( ary::idl::CodeEntity & io_rCe )
{
    if (pDocu)
    {
        io_rCe.Set_Docu(pDocu.Release());
    }
    else if // KORR_FUTURE
            // Re-enable doc-warning for Enum Values, as soon as there is a
            //   @option -no-doc-for-enumvalues.
            (     io_rCe.ClassId() != ary::idl::Module::class_id
              AND io_rCe.ClassId() != ary::idl::EnumValue::class_id  )
    {
        TheMessages().Out_MissingDoc(
                        io_rCe.LocalName(),
                        ParseInfo().CurFile(),
                        ParseInfo().CurLine() );
    }
}

void
UnoIDL_PE::InitData()
{
    // Needs not anything to do.
}

void
UnoIDL_PE::ReceiveData()
{
    // Needs not anything to do.
}

const ary::idl::Module &
UnoIDL_PE::CurNamespace() const
{
    if ( Parent() != 0 )
        return Parent()->CurNamespace();
    else
    {
        csv_assert(false);
        return *(const ary::idl::Module*)0;
    }
}

const ParserInfo &
UnoIDL_PE::ParseInfo() const
{
    if ( Parent() != 0 )
        return Parent()->ParseInfo();
    else
    {
        csv_assert(false);
        return *(const ParserInfo*)0;
    }
}

}   // namespace uidl
}   // namespace csi

<commit_msg>INTEGRATION: CWS warnings01 (1.9.4); FILE MERGED 2005/10/19 09:29:04 np 1.9.4.2: #i53898# 2005/10/18 08:36:16 np 1.9.4.1: #i53898#<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: parsenv2.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 12:06:21 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

#include <precomp.h>
#include <s2_luidl/parsenv2.hxx>

// NOT FULLY DEFINED SERVICES
#include <ary/ary.hxx>
#include <ary/qualiname.hxx>
#include <ary_i/codeinf2.hxx>
#include <ary/idl/i_gate.hxx>
#include <ary/idl/i_ce.hxx>
#include <ary/idl/i_enumvalue.hxx>
#include <ary/idl/ip_ce.hxx>
#include <parser/parserinfo.hxx>
#include <adc_msg.hxx>
#include <s2_luidl/uidl_tok.hxx>
#include <x_parse2.hxx>

namespace csi
{
namespace uidl
{

UnoIDL_PE::~UnoIDL_PE()
{
}

void
UnoIDL_PE::EstablishContacts( UnoIDL_PE *               io_pParentPE,
                              ary::n22::Repository &    io_rRepository,
                              TokenProcessing_Result &  o_rResult )
{
    pRepository = &io_rRepository;
    aMyNode.EstablishContacts(io_pParentPE, io_rRepository.Gate_Idl(), o_rResult);
}

//void
//UnoIDL_PE::EstablishContacts( UnoIDL_PE *             io_pParentPE,
//                            ary::idl::Gate &          io_rGate,
//                            TokenProcessing_Result &  o_rResult )
//{
//  aMyNode.EstablishContacts(io_pParentPE, io_rGate, o_rResult);
//}

void
UnoIDL_PE::Enter( E_EnvStackAction  i_eWayOfEntering )
{
    switch (i_eWayOfEntering)
    {
        case push_sure:
                InitData();
                break;
        case push_try:
                csv_assert(false);
                break;
        case pop_success:
                ReceiveData();
                break;
        case pop_failure:
                throw X_AutodocParser(X_AutodocParser::x_Any);
                // no break because of throw
        default:
            csv_assert(false);
    }   // end switch
}

void
UnoIDL_PE::Leave( E_EnvStackAction  i_eWayOfLeaving )
{
    switch (i_eWayOfLeaving)
    {
        case push_sure:
                break;
        case push_try:
                csv_assert(false);
                break;
        case pop_success:
                TransferData();
                break;
        case pop_failure:
                throw X_AutodocParser(X_AutodocParser::x_Any);
                // no break because of throw
        default:
            csv_assert(false);
    }   // end switch
}

void
UnoIDL_PE::SetDocu( DYN ary::info::CodeInformation * let_dpDocu )
{
    pDocu = let_dpDocu;
}

void
UnoIDL_PE::SetPublished()
{
    if (NOT pDocu)
    {
        pDocu = new ary::info::CodeInformation;
    }
    pDocu->SetPublished();
}

void
UnoIDL_PE::SetOptional()
{
    if (NOT pDocu)
    {
        pDocu = new ary::info::CodeInformation;
    }
    pDocu->SetOptional();
}

void
UnoIDL_PE::PassDocuAt( ary::idl::CodeEntity & io_rCe )
{
    if (pDocu)
    {
        io_rCe.Set_Docu(pDocu.Release());
    }
    else if // KORR_FUTURE
            // Re-enable doc-warning for Enum Values, as soon as there is a
            //   @option -no-doc-for-enumvalues.
            (     io_rCe.ClassId() != ary::idl::Module::class_id
              AND io_rCe.ClassId() != ary::idl::EnumValue::class_id  )
    {
        TheMessages().Out_MissingDoc(
                        io_rCe.LocalName(),
                        ParseInfo().CurFile(),
                        ParseInfo().CurLine() );
    }
}

void
UnoIDL_PE::InitData()
{
    // Needs not anything to do.
}

void
UnoIDL_PE::ReceiveData()
{
    // Needs not anything to do.
}

const ary::idl::Module &
UnoIDL_PE::CurNamespace() const
{
    if ( Parent() != 0 )
        return Parent()->CurNamespace();
    else
    {
        csv_assert(false);
        return *(const ary::idl::Module*)0;
    }
}

const ParserInfo &
UnoIDL_PE::ParseInfo() const
{
    if ( Parent() != 0 )
        return Parent()->ParseInfo();
    else
    {
        csv_assert(false);
        return *(const ParserInfo*)0;
    }
}

UnoIDL_PE::UnoIDL_PE()
    :   aMyNode(),
        pDocu(),
        pRepository(0)
{
}

}   // namespace uidl
}   // namespace csi
<|endoftext|>


<commit_before>#include <QtPlugin>
\
#include "animatedtilesplugin.h"
#include "animatedtilesitem.h"

AnimatedTilesPlugin::AnimatedTilesPlugin()
{
    this->mName = "AnimatedTiles";
    //This should not be an advertized plugin until it is implemented
    //this->mRole = "animatedTiles";
}

Q_EXPORT_PLUGIN2(animatedTiles, AnimatedTilesPlugin)

void AnimatedTilesPlugin::registerPlugin(QDeclarativeContext *context)
{
    qmlRegisterType<AnimatedTilesItem>("AnimatedTiles", 1, 0, "AnimatedTiles");
}
<commit_msg>Adjust minor animated tiles transgression<commit_after>#include <QtPlugin>
\
#include "animatedtilesplugin.h"
#include "animatedtilesitem.h"

AnimatedTilesPlugin::AnimatedTilesPlugin()
{
    setName("AnimatedTiles");
    //This should not be an advertized plugin until it is implemented
    //setRole("animatedTiles");
}

Q_EXPORT_PLUGIN2(animatedTiles, AnimatedTilesPlugin)

void AnimatedTilesPlugin::registerPlugin(QDeclarativeContext *context)
{
    qmlRegisterType<AnimatedTilesItem>("AnimatedTiles", 1, 0, "AnimatedTiles");
}
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** No Commercial Usage
**
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "localplaingdbadapter.h"

#include "gdbengine.h"
#include "procinterrupt.h"
#include "debuggercore.h"
#include "debuggerstringutils.h"

#include <utils/qtcassert.h>

#include <QtCore/QFileInfo>
#include <QtCore/QProcess>
#include <QtGui/QMessageBox>

namespace Debugger {
namespace Internal {

///////////////////////////////////////////////////////////////////////
//
// PlainGdbAdapter
//
///////////////////////////////////////////////////////////////////////

LocalPlainGdbAdapter::LocalPlainGdbAdapter(GdbEngine *engine, QObject *parent)
    : AbstractPlainGdbAdapter(engine, parent)
{
    // Output
    connect(&m_outputCollector, SIGNAL(byteDelivery(QByteArray)),
        engine, SLOT(readDebugeeOutput(QByteArray)));
}

AbstractGdbAdapter::DumperHandling LocalPlainGdbAdapter::dumperHandling() const
{
    // LD_PRELOAD fails for System-Qt on Mac.
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
    return DumperLoadedByGdb;
#else
    return DumperLoadedByGdbPreload;
#endif
}

void LocalPlainGdbAdapter::startAdapter()
{
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
    showMessage(_("TRYING TO START ADAPTER"));

#ifdef Q_OS_WIN
    if (!prepareWinCommand())
        return;
#endif

    QStringList gdbArgs;

    if (!m_outputCollector.listen()) {
        m_engine->handleAdapterStartFailed(tr("Cannot set up communication with child process: %1")
                .arg(m_outputCollector.errorString()), QString());
        return;
    }
    gdbArgs.append(_("--tty=") + m_outputCollector.serverName());

    if (!startParameters().workingDirectory.isEmpty())
        m_gdbProc.setWorkingDirectory(startParameters().workingDirectory);
    if (startParameters().environment.size())
        m_gdbProc.setEnvironment(startParameters().environment.toStringList());

    if (!m_engine->startGdb(gdbArgs)) {
        m_outputCollector.shutdown();
        return;
    }

    checkForReleaseBuild();
    m_engine->handleAdapterStarted();
}

void LocalPlainGdbAdapter::setupInferior()
{
    AbstractPlainGdbAdapter::setupInferior();
}

void LocalPlainGdbAdapter::runEngine()
{
    AbstractPlainGdbAdapter::runEngine();
}

void LocalPlainGdbAdapter::shutdownInferior()
{
    m_engine->defaultInferiorShutdown("kill");
}

void LocalPlainGdbAdapter::shutdownAdapter()
{
    showMessage(_("PLAIN ADAPTER SHUTDOWN %1").arg(state()));
    m_outputCollector.shutdown();
    m_engine->notifyAdapterShutdownOk();
}

void LocalPlainGdbAdapter::checkForReleaseBuild()
{
    // Quick check for a "release" build
    QProcess proc;
    QStringList args;
    args.append(_("-h"));
    args.append(_("-j"));
    args.append(_(".debug_info"));
    args.append(startParameters().executable);
    proc.start(_("objdump"), args);
    proc.closeWriteChannel();
    if (!proc.waitForStarted()) {
        showMessage(_("OBJDUMP PROCESS COULD NOT BE STARTED. "
            "RELEASE BUILD CHECK WILL FAIL"));
        return;
    }
    proc.waitForFinished();
    QByteArray ba = proc.readAllStandardOutput();
    // This should yield something like
    // "debuggertest:     file format elf32-i386\n\n"
    // "Sections:\nIdx Name          Size      VMA       LMA       File off  Algn\n"
    // "30 .debug_info   00087d36  00000000  00000000  0006bbd5  2**0\n"
    // " CONTENTS, READONLY, DEBUGGING"
    if (ba.contains("Sections:") && !ba.contains(".debug_info")) {
        showMessageBox(QMessageBox::Information, "Warning",
           tr("This does not seem to be a \"Debug\" build.\n"
              "Setting breakpoints by file name and line number may fail."));
    }
}

void LocalPlainGdbAdapter::interruptInferior()
{
    const qint64 attachedPID = m_engine->inferiorPid();
    if (attachedPID <= 0) {
        showMessage(_("TRYING TO INTERRUPT INFERIOR BEFORE PID WAS OBTAINED"));
        return;
    }

    if (!interruptProcess(attachedPID)) {
        showMessage(_("CANNOT INTERRUPT %1").arg(attachedPID));
        m_engine->notifyInferiorStopFailed();
    }
}

QByteArray LocalPlainGdbAdapter::execFilePath() const
{
    return QFileInfo(startParameters().executable)
            .absoluteFilePath().toLocal8Bit();
}

bool LocalPlainGdbAdapter::infoTargetNecessary() const
{
#ifdef Q_OS_LINUX
    return true;
#else
    return false;
#endif
}

QByteArray LocalPlainGdbAdapter::toLocalEncoding(const QString &s) const
{
    return s.toLocal8Bit();
}

QString LocalPlainGdbAdapter::fromLocalEncoding(const QByteArray &b) const
{
    return QString::fromLocal8Bit(b);
}

} // namespace Internal
} // namespace Debugger
<commit_msg>debugger: be a bit more verbose in the log on process interruption<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** No Commercial Usage
**
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "localplaingdbadapter.h"

#include "gdbengine.h"
#include "procinterrupt.h"
#include "debuggercore.h"
#include "debuggerstringutils.h"

#include <utils/qtcassert.h>

#include <QtCore/QFileInfo>
#include <QtCore/QProcess>
#include <QtGui/QMessageBox>

namespace Debugger {
namespace Internal {

///////////////////////////////////////////////////////////////////////
//
// PlainGdbAdapter
//
///////////////////////////////////////////////////////////////////////

LocalPlainGdbAdapter::LocalPlainGdbAdapter(GdbEngine *engine, QObject *parent)
    : AbstractPlainGdbAdapter(engine, parent)
{
    // Output
    connect(&m_outputCollector, SIGNAL(byteDelivery(QByteArray)),
        engine, SLOT(readDebugeeOutput(QByteArray)));
}

AbstractGdbAdapter::DumperHandling LocalPlainGdbAdapter::dumperHandling() const
{
    // LD_PRELOAD fails for System-Qt on Mac.
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
    return DumperLoadedByGdb;
#else
    return DumperLoadedByGdbPreload;
#endif
}

void LocalPlainGdbAdapter::startAdapter()
{
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
    showMessage(_("TRYING TO START ADAPTER"));

#ifdef Q_OS_WIN
    if (!prepareWinCommand())
        return;
#endif

    QStringList gdbArgs;

    if (!m_outputCollector.listen()) {
        m_engine->handleAdapterStartFailed(tr("Cannot set up communication with child process: %1")
                .arg(m_outputCollector.errorString()), QString());
        return;
    }
    gdbArgs.append(_("--tty=") + m_outputCollector.serverName());

    if (!startParameters().workingDirectory.isEmpty())
        m_gdbProc.setWorkingDirectory(startParameters().workingDirectory);
    if (startParameters().environment.size())
        m_gdbProc.setEnvironment(startParameters().environment.toStringList());

    if (!m_engine->startGdb(gdbArgs)) {
        m_outputCollector.shutdown();
        return;
    }

    checkForReleaseBuild();
    m_engine->handleAdapterStarted();
}

void LocalPlainGdbAdapter::setupInferior()
{
    AbstractPlainGdbAdapter::setupInferior();
}

void LocalPlainGdbAdapter::runEngine()
{
    AbstractPlainGdbAdapter::runEngine();
}

void LocalPlainGdbAdapter::shutdownInferior()
{
    m_engine->defaultInferiorShutdown("kill");
}

void LocalPlainGdbAdapter::shutdownAdapter()
{
    showMessage(_("PLAIN ADAPTER SHUTDOWN %1").arg(state()));
    m_outputCollector.shutdown();
    m_engine->notifyAdapterShutdownOk();
}

void LocalPlainGdbAdapter::checkForReleaseBuild()
{
    // Quick check for a "release" build
    QProcess proc;
    QStringList args;
    args.append(_("-h"));
    args.append(_("-j"));
    args.append(_(".debug_info"));
    args.append(startParameters().executable);
    proc.start(_("objdump"), args);
    proc.closeWriteChannel();
    if (!proc.waitForStarted()) {
        showMessage(_("OBJDUMP PROCESS COULD NOT BE STARTED. "
            "RELEASE BUILD CHECK WILL FAIL"));
        return;
    }
    proc.waitForFinished();
    QByteArray ba = proc.readAllStandardOutput();
    // This should yield something like
    // "debuggertest:     file format elf32-i386\n\n"
    // "Sections:\nIdx Name          Size      VMA       LMA       File off  Algn\n"
    // "30 .debug_info   00087d36  00000000  00000000  0006bbd5  2**0\n"
    // " CONTENTS, READONLY, DEBUGGING"
    if (ba.contains("Sections:") && !ba.contains(".debug_info")) {
        showMessageBox(QMessageBox::Information, "Warning",
           tr("This does not seem to be a \"Debug\" build.\n"
              "Setting breakpoints by file name and line number may fail."));
    }
}

void LocalPlainGdbAdapter::interruptInferior()
{
    const qint64 attachedPID = m_engine->inferiorPid();
    if (attachedPID <= 0) {
        showMessage(_("TRYING TO INTERRUPT INFERIOR BEFORE PID WAS OBTAINED"));
        return;
    }

    if (interruptProcess(attachedPID)) {
        showMessage(_("INTERRUPTED %1").arg(attachedPID));
    } else {
        showMessage(_("CANNOT INTERRUPT %1").arg(attachedPID));
        m_engine->notifyInferiorStopFailed();
    }
}

QByteArray LocalPlainGdbAdapter::execFilePath() const
{
    return QFileInfo(startParameters().executable)
            .absoluteFilePath().toLocal8Bit();
}

bool LocalPlainGdbAdapter::infoTargetNecessary() const
{
#ifdef Q_OS_LINUX
    return true;
#else
    return false;
#endif
}

QByteArray LocalPlainGdbAdapter::toLocalEncoding(const QString &s) const
{
    return s.toLocal8Bit();
}

QString LocalPlainGdbAdapter::fromLocalEncoding(const QByteArray &b) const
{
    return QString::fromLocal8Bit(b);
}

} // namespace Internal
} // namespace Debugger
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "projecttreewidget.h"

#include "projectexplorer.h"
#include "projectnodes.h"
#include "project.h"
#include "session.h"
#include "projectexplorerconstants.h"
#include "projectmodels.h"

#include <coreplugin/actionmanager/command.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/icontext.h>

#include <utils/qtcassert.h>
#include <utils/navigationtreeview.h>

#include <QDebug>
#include <QSettings>

#include <QHeaderView>
#include <QTreeView>
#include <QVBoxLayout>
#include <QToolButton>
#include <QFocusEvent>
#include <QAction>
#include <QPalette>
#include <QMenu>

using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;

namespace {
    bool debug = false;
}

class ProjectTreeView : public Utils::NavigationTreeView
{
public:
    ProjectTreeView()
    {
        setEditTriggers(QAbstractItemView::EditKeyPressed);
        setContextMenuPolicy(Qt::CustomContextMenu);
//        setExpandsOnDoubleClick(false);
        m_context = new Core::IContext(this);
        m_context->setContext(Core::Context(Constants::C_PROJECT_TREE));
        m_context->setWidget(this);
        Core::ICore::addContextObject(m_context);
    }
    ~ProjectTreeView()
    {
        Core::ICore::removeContextObject(m_context);
        delete m_context;
    }

private:
    Core::IContext *m_context;
};

/*!
  /class ProjectTreeWidget

  Shows the projects in form of a tree.
  */
ProjectTreeWidget::ProjectTreeWidget(QWidget *parent)
        : QWidget(parent),
          m_explorer(ProjectExplorerPlugin::instance()),
          m_view(0),
          m_model(0),
          m_filterProjectsAction(0),
          m_autoSync(false),
          m_autoExpand(true)
{
    m_model = new FlatModel(m_explorer->session()->sessionNode(), this);
    Project *pro = m_explorer->session()->startupProject();
    if (pro)
        m_model->setStartupProject(pro->rootProjectNode());
    NodesWatcher *watcher = new NodesWatcher(this);
    m_explorer->session()->sessionNode()->registerWatcher(watcher);

    connect(watcher, SIGNAL(foldersAboutToBeRemoved(FolderNode*,QList<FolderNode*>)),
            this, SLOT(foldersAboutToBeRemoved(FolderNode*,QList<FolderNode*>)));
    connect(watcher, SIGNAL(filesAboutToBeRemoved(FolderNode*,QList<FileNode*>)),
            this, SLOT(filesAboutToBeRemoved(FolderNode*,QList<FileNode*>)));

    m_view = new ProjectTreeView;
    m_view->setModel(m_model);
    setFocusProxy(m_view);
    initView();

    QVBoxLayout *layout = new QVBoxLayout();
    layout->addWidget(m_view);
    layout->setContentsMargins(0, 0, 0, 0);
    setLayout(layout);

    m_filterProjectsAction = new QAction(tr("Simplify Tree"), this);
    m_filterProjectsAction->setCheckable(true);
    m_filterProjectsAction->setChecked(false); // default is the traditional complex tree
    connect(m_filterProjectsAction, SIGNAL(toggled(bool)), this, SLOT(setProjectFilter(bool)));

    m_filterGeneratedFilesAction = new QAction(tr("Hide Generated Files"), this);
    m_filterGeneratedFilesAction->setCheckable(true);
    m_filterGeneratedFilesAction->setChecked(true);
    connect(m_filterGeneratedFilesAction, SIGNAL(toggled(bool)), this, SLOT(setGeneratedFilesFilter(bool)));

    // connections
    connect(m_model, SIGNAL(modelReset()),
            this, SLOT(initView()));
    connect(m_view, SIGNAL(activated(QModelIndex)),
            this, SLOT(openItem(QModelIndex)));
    connect(m_view->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
            this, SLOT(handleCurrentItemChange(QModelIndex)));
    connect(m_view, SIGNAL(customContextMenuRequested(QPoint)),
            this, SLOT(showContextMenu(QPoint)));
    connect(m_explorer->session(), SIGNAL(singleProjectAdded(ProjectExplorer::Project*)),
            this, SLOT(handleProjectAdded(ProjectExplorer::Project*)));
    connect(m_explorer->session(), SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
            this, SLOT(startupProjectChanged(ProjectExplorer::Project*)));

    connect(m_explorer->session(), SIGNAL(aboutToLoadSession(QString)),
            this, SLOT(disableAutoExpand()));
    connect(m_explorer->session(), SIGNAL(sessionLoaded(QString)),
            this, SLOT(loadExpandData()));
    connect(m_explorer->session(), SIGNAL(aboutToSaveSession()),
            this, SLOT(saveExpandData()));

    m_toggleSync = new QToolButton;
    m_toggleSync->setIcon(QIcon(QLatin1String(Core::Constants::ICON_LINK)));
    m_toggleSync->setCheckable(true);
    m_toggleSync->setChecked(autoSynchronization());
    m_toggleSync->setToolTip(tr("Synchronize with Editor"));
    connect(m_toggleSync, SIGNAL(clicked(bool)), this, SLOT(toggleAutoSynchronization()));

    setAutoSynchronization(true);
}

void ProjectTreeWidget::disableAutoExpand()
{
    m_autoExpand = false;
}

void ProjectTreeWidget::loadExpandData()
{
    m_autoExpand = true;
    QStringList data = m_explorer->session()->value(QLatin1String("ProjectTree.ExpandData")).toStringList();
    recursiveLoadExpandData(m_view->rootIndex(), data.toSet());
}

void ProjectTreeWidget::recursiveLoadExpandData(const QModelIndex &index, const QSet<QString> &data)
{
    if (data.contains(m_model->nodeForIndex(index)->path())) {
        m_view->expand(index);
        int count = m_model->rowCount(index);
        for (int i = 0; i < count; ++i)
            recursiveLoadExpandData(index.child(i, 0), data);
    }
}

void ProjectTreeWidget::saveExpandData()
{
    QStringList data;
    recursiveSaveExpandData(m_view->rootIndex(), &data);
    // TODO if there are multiple ProjectTreeWidgets, the last one saves the data
    m_explorer->session()->setValue(QLatin1String("ProjectTree.ExpandData"), data);
}

void ProjectTreeWidget::recursiveSaveExpandData(const QModelIndex &index, QStringList *data)
{
    Q_ASSERT(data);
    if (m_view->isExpanded(index)) {
        data->append(m_model->nodeForIndex(index)->path());
        int count = m_model->rowCount(index);
        for (int i = 0; i < count; ++i)
            recursiveSaveExpandData(index.child(i, 0), data);
    }
}

void ProjectTreeWidget::foldersAboutToBeRemoved(FolderNode *, const QList<FolderNode*> &list)
{
    Node *n = m_explorer->currentNode();
    while (n) {
        if (FolderNode *fn = qobject_cast<FolderNode *>(n)) {
            if (list.contains(fn)) {
                ProjectNode *pn = n->projectNode();
                // Make sure the node we are switching too isn't going to be removed also
                while (list.contains(pn))
                    pn = pn->parentFolderNode()->projectNode();
                m_explorer->setCurrentNode(pn);
                break;
            }
        }
        n = n->parentFolderNode();
    }
}

void ProjectTreeWidget::filesAboutToBeRemoved(FolderNode *, const QList<FileNode*> &list)
{
    if (FileNode *fileNode = qobject_cast<FileNode *>(m_explorer->currentNode())) {
        if (list.contains(fileNode))
            m_explorer->setCurrentNode(fileNode->projectNode());
    }
}

QToolButton *ProjectTreeWidget::toggleSync()
{
    return m_toggleSync;
}

void ProjectTreeWidget::toggleAutoSynchronization()
{
    setAutoSynchronization(!m_autoSync);
}

bool ProjectTreeWidget::autoSynchronization() const
{
    return m_autoSync;
}

void ProjectTreeWidget::setAutoSynchronization(bool sync, bool syncNow)
{
    m_toggleSync->setChecked(sync);
    if (sync == m_autoSync)
        return;

    m_autoSync = sync;

    if (debug)
        qDebug() << (m_autoSync ? "Enabling auto synchronization" : "Disabling auto synchronization");
    if (m_autoSync) {
        connect(m_explorer, SIGNAL(currentNodeChanged(ProjectExplorer::Node*,ProjectExplorer::Project*)),
                this, SLOT(setCurrentItem(ProjectExplorer::Node*,ProjectExplorer::Project*)));
        if (syncNow)
            setCurrentItem(m_explorer->currentNode(), ProjectExplorerPlugin::currentProject());
    } else {
        disconnect(m_explorer, SIGNAL(currentNodeChanged(ProjectExplorer::Node*,ProjectExplorer::Project*)),
                this, SLOT(setCurrentItem(ProjectExplorer::Node*,ProjectExplorer::Project*)));
    }
}

void ProjectTreeWidget::collapseAll()
{
    m_view->collapseAll();
}

void ProjectTreeWidget::editCurrentItem()
{
    if (m_view->selectionModel()->currentIndex().isValid())
        m_view->edit(m_view->selectionModel()->currentIndex());
}

void ProjectTreeWidget::setCurrentItem(Node *node, Project *project)
{
    if (debug)
        qDebug() << "ProjectTreeWidget::setCurrentItem(" << (project ? project->displayName() : QLatin1String("0"))
                 << ", " <<  (node ? node->path() : QLatin1String("0")) << ")";

    if (!project)
        return;

    const QModelIndex mainIndex = m_model->indexForNode(node);

    if (mainIndex.isValid() && mainIndex != m_view->selectionModel()->currentIndex()) {
        m_view->setCurrentIndex(mainIndex);
        m_view->scrollTo(mainIndex);
    } else {
        if (debug)
            qDebug() << "clear selection";
        m_view->clearSelection();
    }

}

void ProjectTreeWidget::handleCurrentItemChange(const QModelIndex &current)
{
    Node *node = m_model->nodeForIndex(current);
    // node might be 0. that's okay
    bool autoSync = autoSynchronization();
    setAutoSynchronization(false);
    m_explorer->setCurrentNode(node);
    setAutoSynchronization(autoSync, false);
}

void ProjectTreeWidget::showContextMenu(const QPoint &pos)
{
    QModelIndex index = m_view->indexAt(pos);
    Node *node = m_model->nodeForIndex(index);
    m_explorer->showContextMenu(this, m_view->mapToGlobal(pos), node);
}

void ProjectTreeWidget::handleProjectAdded(ProjectExplorer::Project *project)
{
    Node *node = project->rootProjectNode();
    QModelIndex idx = m_model->indexForNode(node);
    if (m_autoExpand) // disabled while session restoring
        m_view->setExpanded(idx, true);
    m_view->setCurrentIndex(idx);
}

void ProjectTreeWidget::startupProjectChanged(ProjectExplorer::Project *project)
{
    if (project) {
        ProjectNode *node = project->rootProjectNode();
        m_model->setStartupProject(node);
    } else {
        m_model->setStartupProject(0);
    }
}

void ProjectTreeWidget::initView()
{
    QModelIndex sessionIndex = m_model->index(0, 0);

    // hide root folder
    m_view->setRootIndex(sessionIndex);

    while (m_model->canFetchMore(sessionIndex))
        m_model->fetchMore(sessionIndex);

    // expand top level projects
    for (int i = 0; i < m_model->rowCount(sessionIndex); ++i)
        m_view->expand(m_model->index(i, 0, sessionIndex));

    setCurrentItem(m_explorer->currentNode(), ProjectExplorerPlugin::currentProject());
}

void ProjectTreeWidget::openItem(const QModelIndex &mainIndex)
{
    Node *node = m_model->nodeForIndex(mainIndex);
    if (node->nodeType() == FileNodeType)
        Core::EditorManager::openEditor(node->path(), Core::Id(), Core::EditorManager::ModeSwitch);
}

void ProjectTreeWidget::setProjectFilter(bool filter)
{
    m_model->setProjectFilterEnabled(filter);
    m_filterProjectsAction->setChecked(filter);
}

void ProjectTreeWidget::setGeneratedFilesFilter(bool filter)
{
    m_model->setGeneratedFilesFilterEnabled(filter);
    m_filterGeneratedFilesAction->setChecked(filter);
}

bool ProjectTreeWidget::generatedFilesFilter()
{
    return m_model->generatedFilesFilterEnabled();
}

bool ProjectTreeWidget::projectFilter()
{
    return m_model->projectFilterEnabled();
}

ProjectTreeWidgetFactory::ProjectTreeWidgetFactory()
{
}

ProjectTreeWidgetFactory::~ProjectTreeWidgetFactory()
{
}

QString ProjectTreeWidgetFactory::displayName() const
{
    return tr("Projects");
}

int ProjectTreeWidgetFactory::priority() const
{
    return 100;
}

Core::Id ProjectTreeWidgetFactory::id() const
{
    return Core::Id("Projects");
}

QKeySequence ProjectTreeWidgetFactory::activationSequence() const
{
    return QKeySequence(Core::UseMacShortcuts ? tr("Meta+X") : tr("Alt+X"));
}

Core::NavigationView ProjectTreeWidgetFactory::createWidget()
{
    Core::NavigationView n;
    ProjectTreeWidget *ptw = new ProjectTreeWidget;
    n.widget = ptw;

    QToolButton *filter = new QToolButton;
    filter->setIcon(QIcon(QLatin1String(Core::Constants::ICON_FILTER)));
    filter->setToolTip(tr("Filter Tree"));
    filter->setPopupMode(QToolButton::InstantPopup);
    filter->setProperty("noArrow", true);
    QMenu *filterMenu = new QMenu(filter);
    filterMenu->addAction(ptw->m_filterProjectsAction);
    filterMenu->addAction(ptw->m_filterGeneratedFilesAction);
    filter->setMenu(filterMenu);

    n.dockToolBarWidgets << filter << ptw->toggleSync();
    return n;
}

void ProjectTreeWidgetFactory::saveSettings(int position, QWidget *widget)
{
    ProjectTreeWidget *ptw = qobject_cast<ProjectTreeWidget *>(widget);
    Q_ASSERT(ptw);
    QSettings *settings = Core::ICore::settings();
    const QString baseKey = QLatin1String("ProjectTreeWidget.") + QString::number(position);
    settings->setValue(baseKey + QLatin1String(".ProjectFilter"), ptw->projectFilter());
    settings->setValue(baseKey + QLatin1String(".GeneratedFilter"), ptw->generatedFilesFilter());
    settings->setValue(baseKey + QLatin1String(".SyncWithEditor"), ptw->autoSynchronization());
}

void ProjectTreeWidgetFactory::restoreSettings(int position, QWidget *widget)
{
    ProjectTreeWidget *ptw = qobject_cast<ProjectTreeWidget *>(widget);
    Q_ASSERT(ptw);
    QSettings *settings = Core::ICore::settings();
    const QString baseKey = QLatin1String("ProjectTreeWidget.") + QString::number(position);
    ptw->setProjectFilter(settings->value(baseKey + QLatin1String(".ProjectFilter"), false).toBool());
    ptw->setGeneratedFilesFilter(settings->value(baseKey + QLatin1String(".GeneratedFilter"), true).toBool());
    ptw->setAutoSynchronization(settings->value(baseKey +  QLatin1String(".SyncWithEditor"), true).toBool());
}
<commit_msg>ProjectTreeWidget: Use Core namespace<commit_after>/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "projecttreewidget.h"

#include "projectexplorer.h"
#include "projectnodes.h"
#include "project.h"
#include "session.h"
#include "projectexplorerconstants.h"
#include "projectmodels.h"

#include <coreplugin/actionmanager/command.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/icontext.h>

#include <utils/qtcassert.h>
#include <utils/navigationtreeview.h>

#include <QDebug>
#include <QSettings>

#include <QHeaderView>
#include <QTreeView>
#include <QVBoxLayout>
#include <QToolButton>
#include <QFocusEvent>
#include <QAction>
#include <QPalette>
#include <QMenu>

using namespace Core;
using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;

namespace {
    bool debug = false;
}

class ProjectTreeView : public Utils::NavigationTreeView
{
public:
    ProjectTreeView()
    {
        setEditTriggers(QAbstractItemView::EditKeyPressed);
        setContextMenuPolicy(Qt::CustomContextMenu);
        m_context = new IContext(this);
        m_context->setContext(Context(ProjectExplorer::Constants::C_PROJECT_TREE));
        m_context->setWidget(this);
        ICore::addContextObject(m_context);
    }
    ~ProjectTreeView()
    {
        ICore::removeContextObject(m_context);
        delete m_context;
    }

private:
    IContext *m_context;
};

/*!
  /class ProjectTreeWidget

  Shows the projects in form of a tree.
  */
ProjectTreeWidget::ProjectTreeWidget(QWidget *parent)
        : QWidget(parent),
          m_explorer(ProjectExplorerPlugin::instance()),
          m_view(0),
          m_model(0),
          m_filterProjectsAction(0),
          m_autoSync(false),
          m_autoExpand(true)
{
    m_model = new FlatModel(m_explorer->session()->sessionNode(), this);
    Project *pro = m_explorer->session()->startupProject();
    if (pro)
        m_model->setStartupProject(pro->rootProjectNode());
    NodesWatcher *watcher = new NodesWatcher(this);
    m_explorer->session()->sessionNode()->registerWatcher(watcher);

    connect(watcher, SIGNAL(foldersAboutToBeRemoved(FolderNode*,QList<FolderNode*>)),
            this, SLOT(foldersAboutToBeRemoved(FolderNode*,QList<FolderNode*>)));
    connect(watcher, SIGNAL(filesAboutToBeRemoved(FolderNode*,QList<FileNode*>)),
            this, SLOT(filesAboutToBeRemoved(FolderNode*,QList<FileNode*>)));

    m_view = new ProjectTreeView;
    m_view->setModel(m_model);
    setFocusProxy(m_view);
    initView();

    QVBoxLayout *layout = new QVBoxLayout();
    layout->addWidget(m_view);
    layout->setContentsMargins(0, 0, 0, 0);
    setLayout(layout);

    m_filterProjectsAction = new QAction(tr("Simplify Tree"), this);
    m_filterProjectsAction->setCheckable(true);
    m_filterProjectsAction->setChecked(false); // default is the traditional complex tree
    connect(m_filterProjectsAction, SIGNAL(toggled(bool)), this, SLOT(setProjectFilter(bool)));

    m_filterGeneratedFilesAction = new QAction(tr("Hide Generated Files"), this);
    m_filterGeneratedFilesAction->setCheckable(true);
    m_filterGeneratedFilesAction->setChecked(true);
    connect(m_filterGeneratedFilesAction, SIGNAL(toggled(bool)), this, SLOT(setGeneratedFilesFilter(bool)));

    // connections
    connect(m_model, SIGNAL(modelReset()),
            this, SLOT(initView()));
    connect(m_view, SIGNAL(activated(QModelIndex)),
            this, SLOT(openItem(QModelIndex)));
    connect(m_view->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
            this, SLOT(handleCurrentItemChange(QModelIndex)));
    connect(m_view, SIGNAL(customContextMenuRequested(QPoint)),
            this, SLOT(showContextMenu(QPoint)));
    connect(m_explorer->session(), SIGNAL(singleProjectAdded(ProjectExplorer::Project*)),
            this, SLOT(handleProjectAdded(ProjectExplorer::Project*)));
    connect(m_explorer->session(), SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
            this, SLOT(startupProjectChanged(ProjectExplorer::Project*)));

    connect(m_explorer->session(), SIGNAL(aboutToLoadSession(QString)),
            this, SLOT(disableAutoExpand()));
    connect(m_explorer->session(), SIGNAL(sessionLoaded(QString)),
            this, SLOT(loadExpandData()));
    connect(m_explorer->session(), SIGNAL(aboutToSaveSession()),
            this, SLOT(saveExpandData()));

    m_toggleSync = new QToolButton;
    m_toggleSync->setIcon(QIcon(QLatin1String(Core::Constants::ICON_LINK)));
    m_toggleSync->setCheckable(true);
    m_toggleSync->setChecked(autoSynchronization());
    m_toggleSync->setToolTip(tr("Synchronize with Editor"));
    connect(m_toggleSync, SIGNAL(clicked(bool)), this, SLOT(toggleAutoSynchronization()));

    setAutoSynchronization(true);
}

void ProjectTreeWidget::disableAutoExpand()
{
    m_autoExpand = false;
}

void ProjectTreeWidget::loadExpandData()
{
    m_autoExpand = true;
    QStringList data = m_explorer->session()->value(QLatin1String("ProjectTree.ExpandData")).toStringList();
    recursiveLoadExpandData(m_view->rootIndex(), data.toSet());
}

void ProjectTreeWidget::recursiveLoadExpandData(const QModelIndex &index, const QSet<QString> &data)
{
    if (data.contains(m_model->nodeForIndex(index)->path())) {
        m_view->expand(index);
        int count = m_model->rowCount(index);
        for (int i = 0; i < count; ++i)
            recursiveLoadExpandData(index.child(i, 0), data);
    }
}

void ProjectTreeWidget::saveExpandData()
{
    QStringList data;
    recursiveSaveExpandData(m_view->rootIndex(), &data);
    // TODO if there are multiple ProjectTreeWidgets, the last one saves the data
    m_explorer->session()->setValue(QLatin1String("ProjectTree.ExpandData"), data);
}

void ProjectTreeWidget::recursiveSaveExpandData(const QModelIndex &index, QStringList *data)
{
    Q_ASSERT(data);
    if (m_view->isExpanded(index)) {
        data->append(m_model->nodeForIndex(index)->path());
        int count = m_model->rowCount(index);
        for (int i = 0; i < count; ++i)
            recursiveSaveExpandData(index.child(i, 0), data);
    }
}

void ProjectTreeWidget::foldersAboutToBeRemoved(FolderNode *, const QList<FolderNode*> &list)
{
    Node *n = m_explorer->currentNode();
    while (n) {
        if (FolderNode *fn = qobject_cast<FolderNode *>(n)) {
            if (list.contains(fn)) {
                ProjectNode *pn = n->projectNode();
                // Make sure the node we are switching too isn't going to be removed also
                while (list.contains(pn))
                    pn = pn->parentFolderNode()->projectNode();
                m_explorer->setCurrentNode(pn);
                break;
            }
        }
        n = n->parentFolderNode();
    }
}

void ProjectTreeWidget::filesAboutToBeRemoved(FolderNode *, const QList<FileNode*> &list)
{
    if (FileNode *fileNode = qobject_cast<FileNode *>(m_explorer->currentNode())) {
        if (list.contains(fileNode))
            m_explorer->setCurrentNode(fileNode->projectNode());
    }
}

QToolButton *ProjectTreeWidget::toggleSync()
{
    return m_toggleSync;
}

void ProjectTreeWidget::toggleAutoSynchronization()
{
    setAutoSynchronization(!m_autoSync);
}

bool ProjectTreeWidget::autoSynchronization() const
{
    return m_autoSync;
}

void ProjectTreeWidget::setAutoSynchronization(bool sync, bool syncNow)
{
    m_toggleSync->setChecked(sync);
    if (sync == m_autoSync)
        return;

    m_autoSync = sync;

    if (debug)
        qDebug() << (m_autoSync ? "Enabling auto synchronization" : "Disabling auto synchronization");
    if (m_autoSync) {
        connect(m_explorer, SIGNAL(currentNodeChanged(ProjectExplorer::Node*,ProjectExplorer::Project*)),
                this, SLOT(setCurrentItem(ProjectExplorer::Node*,ProjectExplorer::Project*)));
        if (syncNow)
            setCurrentItem(m_explorer->currentNode(), ProjectExplorerPlugin::currentProject());
    } else {
        disconnect(m_explorer, SIGNAL(currentNodeChanged(ProjectExplorer::Node*,ProjectExplorer::Project*)),
                this, SLOT(setCurrentItem(ProjectExplorer::Node*,ProjectExplorer::Project*)));
    }
}

void ProjectTreeWidget::collapseAll()
{
    m_view->collapseAll();
}

void ProjectTreeWidget::editCurrentItem()
{
    if (m_view->selectionModel()->currentIndex().isValid())
        m_view->edit(m_view->selectionModel()->currentIndex());
}

void ProjectTreeWidget::setCurrentItem(Node *node, Project *project)
{
    if (debug)
        qDebug() << "ProjectTreeWidget::setCurrentItem(" << (project ? project->displayName() : QLatin1String("0"))
                 << ", " <<  (node ? node->path() : QLatin1String("0")) << ")";

    if (!project)
        return;

    const QModelIndex mainIndex = m_model->indexForNode(node);

    if (mainIndex.isValid() && mainIndex != m_view->selectionModel()->currentIndex()) {
        m_view->setCurrentIndex(mainIndex);
        m_view->scrollTo(mainIndex);
    } else {
        if (debug)
            qDebug() << "clear selection";
        m_view->clearSelection();
    }

}

void ProjectTreeWidget::handleCurrentItemChange(const QModelIndex &current)
{
    Node *node = m_model->nodeForIndex(current);
    // node might be 0. that's okay
    bool autoSync = autoSynchronization();
    setAutoSynchronization(false);
    m_explorer->setCurrentNode(node);
    setAutoSynchronization(autoSync, false);
}

void ProjectTreeWidget::showContextMenu(const QPoint &pos)
{
    QModelIndex index = m_view->indexAt(pos);
    Node *node = m_model->nodeForIndex(index);
    m_explorer->showContextMenu(this, m_view->mapToGlobal(pos), node);
}

void ProjectTreeWidget::handleProjectAdded(ProjectExplorer::Project *project)
{
    Node *node = project->rootProjectNode();
    QModelIndex idx = m_model->indexForNode(node);
    if (m_autoExpand) // disabled while session restoring
        m_view->setExpanded(idx, true);
    m_view->setCurrentIndex(idx);
}

void ProjectTreeWidget::startupProjectChanged(ProjectExplorer::Project *project)
{
    if (project) {
        ProjectNode *node = project->rootProjectNode();
        m_model->setStartupProject(node);
    } else {
        m_model->setStartupProject(0);
    }
}

void ProjectTreeWidget::initView()
{
    QModelIndex sessionIndex = m_model->index(0, 0);

    // hide root folder
    m_view->setRootIndex(sessionIndex);

    while (m_model->canFetchMore(sessionIndex))
        m_model->fetchMore(sessionIndex);

    // expand top level projects
    for (int i = 0; i < m_model->rowCount(sessionIndex); ++i)
        m_view->expand(m_model->index(i, 0, sessionIndex));

    setCurrentItem(m_explorer->currentNode(), ProjectExplorerPlugin::currentProject());
}

void ProjectTreeWidget::openItem(const QModelIndex &mainIndex)
{
    Node *node = m_model->nodeForIndex(mainIndex);
    if (node->nodeType() == FileNodeType)
        EditorManager::openEditor(node->path(), Id(), EditorManager::ModeSwitch);
}

void ProjectTreeWidget::setProjectFilter(bool filter)
{
    m_model->setProjectFilterEnabled(filter);
    m_filterProjectsAction->setChecked(filter);
}

void ProjectTreeWidget::setGeneratedFilesFilter(bool filter)
{
    m_model->setGeneratedFilesFilterEnabled(filter);
    m_filterGeneratedFilesAction->setChecked(filter);
}

bool ProjectTreeWidget::generatedFilesFilter()
{
    return m_model->generatedFilesFilterEnabled();
}

bool ProjectTreeWidget::projectFilter()
{
    return m_model->projectFilterEnabled();
}

ProjectTreeWidgetFactory::ProjectTreeWidgetFactory()
{
}

ProjectTreeWidgetFactory::~ProjectTreeWidgetFactory()
{
}

QString ProjectTreeWidgetFactory::displayName() const
{
    return tr("Projects");
}

int ProjectTreeWidgetFactory::priority() const
{
    return 100;
}

Id ProjectTreeWidgetFactory::id() const
{
    return Id("Projects");
}

QKeySequence ProjectTreeWidgetFactory::activationSequence() const
{
    return QKeySequence(UseMacShortcuts ? tr("Meta+X") : tr("Alt+X"));
}

NavigationView ProjectTreeWidgetFactory::createWidget()
{
    NavigationView n;
    ProjectTreeWidget *ptw = new ProjectTreeWidget;
    n.widget = ptw;

    QToolButton *filter = new QToolButton;
    filter->setIcon(QIcon(QLatin1String(Core::Constants::ICON_FILTER)));
    filter->setToolTip(tr("Filter Tree"));
    filter->setPopupMode(QToolButton::InstantPopup);
    filter->setProperty("noArrow", true);
    QMenu *filterMenu = new QMenu(filter);
    filterMenu->addAction(ptw->m_filterProjectsAction);
    filterMenu->addAction(ptw->m_filterGeneratedFilesAction);
    filter->setMenu(filterMenu);

    n.dockToolBarWidgets << filter << ptw->toggleSync();
    return n;
}

void ProjectTreeWidgetFactory::saveSettings(int position, QWidget *widget)
{
    ProjectTreeWidget *ptw = qobject_cast<ProjectTreeWidget *>(widget);
    Q_ASSERT(ptw);
    QSettings *settings = ICore::settings();
    const QString baseKey = QLatin1String("ProjectTreeWidget.") + QString::number(position);
    settings->setValue(baseKey + QLatin1String(".ProjectFilter"), ptw->projectFilter());
    settings->setValue(baseKey + QLatin1String(".GeneratedFilter"), ptw->generatedFilesFilter());
    settings->setValue(baseKey + QLatin1String(".SyncWithEditor"), ptw->autoSynchronization());
}

void ProjectTreeWidgetFactory::restoreSettings(int position, QWidget *widget)
{
    ProjectTreeWidget *ptw = qobject_cast<ProjectTreeWidget *>(widget);
    Q_ASSERT(ptw);
    QSettings *settings = ICore::settings();
    const QString baseKey = QLatin1String("ProjectTreeWidget.") + QString::number(position);
    ptw->setProjectFilter(settings->value(baseKey + QLatin1String(".ProjectFilter"), false).toBool());
    ptw->setGeneratedFilesFilter(settings->value(baseKey + QLatin1String(".GeneratedFilter"), true).toBool());
    ptw->setAutoSynchronization(settings->value(baseKey +  QLatin1String(".SyncWithEditor"), true).toBool());
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014-2021 AscEmu Team <http://www.ascemu.org>
 * Copyright (c) 2008-2015 Sun++ Team <http://www.sunplusplus.info>
 * Copyright (C) 2008-2012 ArcEmu Team <http://www.ArcEmu.org/>
 * Copyright (C) 2008 WEmu Team
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#include "Setup.h"
#include "Server/Script/CreatureAIScript.h"

class TheDormantShade : public QuestScript
{
public:
    void OnQuestComplete(Player* mTarget, QuestLogEntry* /*qLogEntry*/) override
    {
        Creature* creat = mTarget->GetMapMgr()->GetInterface()->SpawnCreature(1946, 2467.314f, 14.8471f, 23.5950f, 0, true, false, 0, 0);
        creat->Despawn(60000, 0);
        creat->sendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "You have disturbed my rest. Now face my wrath!");
    }
};

class CalvinMontague : public CreatureAIScript
{
public:
    static CreatureAIScript* Create(Creature* c) { return new CalvinMontague(c); }
    explicit CalvinMontague(Creature* pCreature) : CreatureAIScript(pCreature) {}

    void OnLoad() override
    {
        getCreature()->SetFaction(68);
        getCreature()->setStandState(STANDSTATE_STAND);
    }

    void OnDamageTaken(Unit* mAttacker, uint32_t /*fAmount*/) override
    {
        if (getCreature()->getHealthPct() < 10)
        {
            if (mAttacker->isPlayer())
            {
                getCreature()->addUnitFlags(UNIT_FLAG_NOT_SELECTABLE);
                if (auto* questLog = static_cast<Player*>(mAttacker)->getQuestLogByQuestId(590))
                {
                    questLog->sendQuestComplete();
                    setScriptPhase(2);
                }
            }
        }
    }

    void OnScriptPhaseChange(uint32_t phase) override
    {
        if (phase == 2)
        {
            getCreature()->sendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "Okay, okay! Enough fighting.");
            getCreature()->RemoveNegativeAuras();
            getCreature()->SetFaction(68);
            getCreature()->setStandState(STANDSTATE_SIT);
            getCreature()->castSpell(getCreature(), sSpellMgr.getSpellInfo(433), true);
            sEventMgr.AddEvent(static_cast<Unit*>(getCreature()), &Unit::setStandState, (uint8_t)STANDSTATE_STAND, EVENT_CREATURE_UPDATE, 18000, 0, 1);
            getCreature()->getThreatManager().clearAllThreat();
            getCreature()->getThreatManager().removeMeFromThreatLists();
            getCreature()->GetAIInterface()->handleEvent(EVENT_LEAVECOMBAT, getCreature(), 0);
            _setMeleeDisabled(true);
            getCreature()->GetAIInterface()->setAllowedToEnterCombat(false);
            getCreature()->removeUnitFlags(UNIT_FLAG_NOT_SELECTABLE);
        }
    }
};

class ARoguesDeal : public QuestScript
{
public:
    void OnQuestStart(Player* mTarget, QuestLogEntry* /*qLogEntry*/) override
    {
        float SSX = mTarget->GetPositionX();
        float SSY = mTarget->GetPositionY();
        float SSZ = mTarget->GetPositionZ();

        Creature* Dashel = mTarget->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(SSX, SSY, SSZ, 6784);

        if (Dashel == nullptr)
            return;

        Dashel->SetFaction(28);
        Dashel->GetAIInterface()->setMeleeDisabled(false);
        Dashel->GetAIInterface()->setAllowedToEnterCombat(true);
    }
};

class Zealot : public CreatureAIScript
{
public:
    static CreatureAIScript* Create(Creature* c) { return new Zealot(c); }
    explicit Zealot(Creature* pCreature) : CreatureAIScript(pCreature) {}

    void OnReachWP(uint32_t type, uint32_t iWaypointId) override
    {
        if (type != WAYPOINT_MOTION_TYPE)
            return;

        if (!getCreature()->HasAura(3287))
            return;
        if (iWaypointId == 2)
        {
            getCreature()->sendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "My mind. . .me flesh. . .I'm. . .rotting. . . .!");
        }

        if (iWaypointId == 7)
        {
            getCreature()->castSpell(getCreature(), sSpellMgr.getSpellInfo(5), true);
        }
    }
};

void SetupTirisfalGlades(ScriptMgr* mgr)
{
    mgr->register_quest_script(410, new TheDormantShade());
    mgr->register_creature_script(6784, &CalvinMontague::Create);
    mgr->register_quest_script(590, new ARoguesDeal());
    mgr->register_creature_script(1931, &Zealot::Create);
}
<commit_msg>UndeadStartQuest<commit_after>/*
 * Copyright (c) 2014-2021 AscEmu Team <http://www.ascemu.org>
 * Copyright (c) 2008-2015 Sun++ Team <http://www.sunplusplus.info>
 * Copyright (C) 2008-2012 ArcEmu Team <http://www.ArcEmu.org/>
 * Copyright (C) 2008 WEmu Team
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#include "Setup.h"
#include "Server/Script/CreatureAIScript.h"

class TheDormantShade : public QuestScript
{
public:
    void OnQuestComplete(Player* mTarget, QuestLogEntry* /*qLogEntry*/) override
    {
        Creature* creat = mTarget->GetMapMgr()->GetInterface()->SpawnCreature(1946, 2467.314f, 14.8471f, 23.5950f, 0, true, false, 0, 0);
        creat->Despawn(60000, 0);
        creat->sendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "You have disturbed my rest. Now face my wrath!");
    }
};

class CalvinMontague : public CreatureAIScript
{
public:
    static CreatureAIScript* Create(Creature* c) { return new CalvinMontague(c); }
    explicit CalvinMontague(Creature* pCreature) : CreatureAIScript(pCreature) {}

    void OnLoad() override
    {
        getCreature()->SetFaction(68);
        getCreature()->setStandState(STANDSTATE_STAND);
    }

    void OnDamageTaken(Unit* mAttacker, uint32_t /*fAmount*/) override
    {
        if (getCreature()->getHealthPct() < 10)
        {
            if (mAttacker->isPlayer())
            {
                getCreature()->addUnitFlags(UNIT_FLAG_NOT_SELECTABLE);
                if (auto* questLog = static_cast<Player*>(mAttacker)->getQuestLogByQuestId(590))
                {
                    questLog->sendQuestComplete();
                    setScriptPhase(2);
                }
            }
        }
    }

    void OnScriptPhaseChange(uint32_t phase) override
    {
        if (phase == 2)
        {
            getCreature()->sendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "Okay, okay! Enough fighting.");
            getCreature()->RemoveNegativeAuras();
            getCreature()->SetFaction(68);
            getCreature()->setStandState(STANDSTATE_SIT);
            getCreature()->castSpell(getCreature(), sSpellMgr.getSpellInfo(433), true);
            sEventMgr.AddEvent(static_cast<Unit*>(getCreature()), &Unit::setStandState, (uint8_t)STANDSTATE_STAND, EVENT_CREATURE_UPDATE, 18000, 0, 1);
            getCreature()->getThreatManager().clearAllThreat();
            getCreature()->getThreatManager().removeMeFromThreatLists();
            getCreature()->GetAIInterface()->handleEvent(EVENT_LEAVECOMBAT, getCreature(), 0);
            _setMeleeDisabled(true);
            getCreature()->GetAIInterface()->setAllowedToEnterCombat(false);
            getCreature()->removeUnitFlags(UNIT_FLAG_NOT_SELECTABLE);
        }
    }
};

class ARoguesDeal : public QuestScript
{
public:
    void OnQuestStart(Player* mTarget, QuestLogEntry* /*qLogEntry*/) override
    {
        float SSX = mTarget->GetPositionX();
        float SSY = mTarget->GetPositionY();
        float SSZ = mTarget->GetPositionZ();

        Creature* Dashel = mTarget->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(SSX, SSY, SSZ, 6784);

        if (Dashel == nullptr)
            return;

        Dashel->SetFaction(28);
        Dashel->GetAIInterface()->setMeleeDisabled(false);
        Dashel->GetAIInterface()->setAllowedToEnterCombat(true);
    }
};

class Zealot : public CreatureAIScript
{
public:
    static CreatureAIScript* Create(Creature* c) { return new Zealot(c); }
    explicit Zealot(Creature* pCreature) : CreatureAIScript(pCreature) {}

    void OnReachWP(uint32_t type, uint32_t iWaypointId) override
    {
        if (type != WAYPOINT_MOTION_TYPE)
            return;

        if (!getCreature()->HasAura(3287))
            return;
        if (iWaypointId == 2)
        {
            getCreature()->sendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "My mind. . .me flesh. . .I'm. . .rotting. . . .!");
        }

        if (iWaypointId == 7)
        {
            getCreature()->castSpell(getCreature(), sSpellMgr.getSpellInfo(5), true);
        }
    }
};

class FreshOutOfTheGrave : public QuestScript
{
public:
    void OnQuestStart(Player* mTarget, QuestLogEntry* /*qLogEntry*/) override
    {
        uint32_t rigorMortisSpell = 73523;
        uint32_t ressurrectSpell = 73524;

        // Ressurect our Player
        mTarget->castSpell(mTarget, sSpellMgr.getSpellInfo(ressurrectSpell), true);

        // Remove death Aura
        if (mTarget->HasAura(rigorMortisSpell))
        {
            mTarget->removeAllAurasById(rigorMortisSpell);
            mTarget->removeSpell(rigorMortisSpell, false, false, 0);
        }
    }
};

void SetupTirisfalGlades(ScriptMgr* mgr)
{
    mgr->register_quest_script(410, new TheDormantShade());
    mgr->register_creature_script(6784, &CalvinMontague::Create);
    mgr->register_quest_script(590, new ARoguesDeal());
    mgr->register_creature_script(1931, &Zealot::Create);
    mgr->register_quest_script(24959, new FreshOutOfTheGrave());
}
<|endoftext|>


<commit_before>#include "precompiled.h"

using namespace mix;

namespace {

class STA_TAOCP_Book_Test : public ::testing::Test
{
private:
	void SetUp() override
	{
		dest_address = 2000;
		dest_cell.set_sign(Sign::Negative);
		dest_cell.set_byte(1, 1);
		dest_cell.set_byte(2, 2);
		dest_cell.set_byte(3, 3);
		dest_cell.set_byte(4, 4);
		dest_cell.set_byte(5, 5);

		mix.set_memory(dest_address, dest_cell);

		Register ra;
		ra.set_sign(Sign::Positive);
		ra.set_byte(1, 6);
		ra.set_byte(2, 7);
		ra.set_byte(3, 8);
		ra.set_byte(4, 9);
		ra.set_byte(5, 10);

		mix.set_ra(ra);
	}

protected:
	const Word& dest_word()
	{
#if defined(__clang__)
#  pragma clang diagnostic push
	// implicit conversion loses integer precision
#  pragma clang diagnostic ignored "-Wshorten-64-to-32"
#endif
		return mix.memory(static_cast<std::size_t>(dest_address));
#if defined(__clang__)
#  pragma clang diagnostic pop
#endif
	}

protected:
	Computer mix;
	Word dest_cell;
	int dest_address;
};
} // namespace

// STA 2000
TEST_F(STA_TAOCP_Book_Test, Default_STA_Stores_All_Word)
{
	mix.execute(MakeSTA(dest_address));
	ASSERT_EQ(mix.ra(), dest_word());
}

// STA 2000(1:5)
TEST_F(STA_TAOCP_Book_Test, STA_With_All_BytesField_Gets_All_Except_Sign)
{
	mix.execute(MakeSTA(dest_address, WordField{1, 5}));

	ASSERT_EQ(dest_word().sign(), Sign::Negative);
	ASSERT_EQ(dest_word().byte(1), 6);
	ASSERT_EQ(dest_word().byte(2), 7);
	ASSERT_EQ(dest_word().byte(3), 8);
	ASSERT_EQ(dest_word().byte(4), 9);
	ASSERT_EQ(dest_word().byte(5), 10);
}

// STA 2000(5:5)
TEST_F(STA_TAOCP_Book_Test, STA_With_RightMost_Field_Sets_Byte_Without_Shift)
{
	mix.execute(MakeSTA(dest_address, WordField{5, 5}));

	ASSERT_EQ(dest_word().sign(), Sign::Negative);
	ASSERT_EQ(dest_word().byte(1), 1);
	ASSERT_EQ(dest_word().byte(2), 2);
	ASSERT_EQ(dest_word().byte(3), 3);
	ASSERT_EQ(dest_word().byte(4), 4);
	ASSERT_EQ(dest_word().byte(5), 10);
}

// STA 2000(2:2)
TEST_F(STA_TAOCP_Book_Test, STA_With_One_ByteField_Length_Gets_Value_From_5_RA_Byte)
{
	mix.execute(MakeSTA(dest_address, WordField{2, 2}));
	ASSERT_EQ(mix.ra().byte(5), dest_word().byte(2));

	ASSERT_EQ(dest_word().sign(), Sign::Negative);
	ASSERT_EQ(dest_word().byte(1), 1);
	ASSERT_EQ(dest_word().byte(2), 10);
	ASSERT_EQ(dest_word().byte(3), 3);
	ASSERT_EQ(dest_word().byte(4), 4);
	ASSERT_EQ(dest_word().byte(5), 5);
}

// STA 2000(2:3)
TEST_F(STA_TAOCP_Book_Test, STA_With_Two_ByteField_Length_Gets_Value_From_Last_Two_RA_Bytes)
{
	mix.execute(MakeSTA(dest_address, WordField{2, 3}));
	ASSERT_EQ(mix.ra().byte(5), dest_word().byte(3));
	ASSERT_EQ(mix.ra().byte(4), dest_word().byte(2));

	ASSERT_EQ(dest_word().sign(), Sign::Negative);
	ASSERT_EQ(dest_word().byte(1), 1);
	ASSERT_EQ(dest_word().byte(2), 9);
	ASSERT_EQ(dest_word().byte(3), 10);
	ASSERT_EQ(dest_word().byte(4), 4);
	ASSERT_EQ(dest_word().byte(5), 5);
}

// STA 2000(0:1)
TEST_F(STA_TAOCP_Book_Test, STA_With_One_Sign_ByteField_Gets_Value_From_5_RA_Byte_And_Its_Sign)
{
	mix.execute(MakeSTA(dest_address, WordField{0, 1}));
	ASSERT_EQ(mix.ra().byte(5), dest_word().byte(1));

	ASSERT_EQ(dest_word().sign(), Sign::Positive);
	ASSERT_EQ(dest_word().byte(1), 10);
	ASSERT_EQ(dest_word().byte(2), 2);
	ASSERT_EQ(dest_word().byte(3), 3);
	ASSERT_EQ(dest_word().byte(4), 4);
	ASSERT_EQ(dest_word().byte(5), 5);
}
<commit_msg>Remove useless static_cast in test<commit_after>#include "precompiled.h"

using namespace mix;

namespace {

class STA_TAOCP_Book_Test : public ::testing::Test
{
private:
	void SetUp() override
	{
		dest_address = 2000;
		dest_cell.set_sign(Sign::Negative);
		dest_cell.set_byte(1, 1);
		dest_cell.set_byte(2, 2);
		dest_cell.set_byte(3, 3);
		dest_cell.set_byte(4, 4);
		dest_cell.set_byte(5, 5);

		mix.set_memory(dest_address, dest_cell);

		Register ra;
		ra.set_sign(Sign::Positive);
		ra.set_byte(1, 6);
		ra.set_byte(2, 7);
		ra.set_byte(3, 8);
		ra.set_byte(4, 9);
		ra.set_byte(5, 10);

		mix.set_ra(ra);
	}

protected:
	const Word& dest_word()
	{
		return mix.memory(dest_address);
	}

protected:
	Computer mix;
	Word dest_cell;
	int dest_address;
};
} // namespace

// STA 2000
TEST_F(STA_TAOCP_Book_Test, Default_STA_Stores_All_Word)
{
	mix.execute(MakeSTA(dest_address));
	ASSERT_EQ(mix.ra(), dest_word());
}

// STA 2000(1:5)
TEST_F(STA_TAOCP_Book_Test, STA_With_All_BytesField_Gets_All_Except_Sign)
{
	mix.execute(MakeSTA(dest_address, WordField{1, 5}));

	ASSERT_EQ(dest_word().sign(), Sign::Negative);
	ASSERT_EQ(dest_word().byte(1), 6);
	ASSERT_EQ(dest_word().byte(2), 7);
	ASSERT_EQ(dest_word().byte(3), 8);
	ASSERT_EQ(dest_word().byte(4), 9);
	ASSERT_EQ(dest_word().byte(5), 10);
}

// STA 2000(5:5)
TEST_F(STA_TAOCP_Book_Test, STA_With_RightMost_Field_Sets_Byte_Without_Shift)
{
	mix.execute(MakeSTA(dest_address, WordField{5, 5}));

	ASSERT_EQ(dest_word().sign(), Sign::Negative);
	ASSERT_EQ(dest_word().byte(1), 1);
	ASSERT_EQ(dest_word().byte(2), 2);
	ASSERT_EQ(dest_word().byte(3), 3);
	ASSERT_EQ(dest_word().byte(4), 4);
	ASSERT_EQ(dest_word().byte(5), 10);
}

// STA 2000(2:2)
TEST_F(STA_TAOCP_Book_Test, STA_With_One_ByteField_Length_Gets_Value_From_5_RA_Byte)
{
	mix.execute(MakeSTA(dest_address, WordField{2, 2}));
	ASSERT_EQ(mix.ra().byte(5), dest_word().byte(2));

	ASSERT_EQ(dest_word().sign(), Sign::Negative);
	ASSERT_EQ(dest_word().byte(1), 1);
	ASSERT_EQ(dest_word().byte(2), 10);
	ASSERT_EQ(dest_word().byte(3), 3);
	ASSERT_EQ(dest_word().byte(4), 4);
	ASSERT_EQ(dest_word().byte(5), 5);
}

// STA 2000(2:3)
TEST_F(STA_TAOCP_Book_Test, STA_With_Two_ByteField_Length_Gets_Value_From_Last_Two_RA_Bytes)
{
	mix.execute(MakeSTA(dest_address, WordField{2, 3}));
	ASSERT_EQ(mix.ra().byte(5), dest_word().byte(3));
	ASSERT_EQ(mix.ra().byte(4), dest_word().byte(2));

	ASSERT_EQ(dest_word().sign(), Sign::Negative);
	ASSERT_EQ(dest_word().byte(1), 1);
	ASSERT_EQ(dest_word().byte(2), 9);
	ASSERT_EQ(dest_word().byte(3), 10);
	ASSERT_EQ(dest_word().byte(4), 4);
	ASSERT_EQ(dest_word().byte(5), 5);
}

// STA 2000(0:1)
TEST_F(STA_TAOCP_Book_Test, STA_With_One_Sign_ByteField_Gets_Value_From_5_RA_Byte_And_Its_Sign)
{
	mix.execute(MakeSTA(dest_address, WordField{0, 1}));
	ASSERT_EQ(mix.ra().byte(5), dest_word().byte(1));

	ASSERT_EQ(dest_word().sign(), Sign::Positive);
	ASSERT_EQ(dest_word().byte(1), 10);
	ASSERT_EQ(dest_word().byte(2), 2);
	ASSERT_EQ(dest_word().byte(3), 3);
	ASSERT_EQ(dest_word().byte(4), 4);
	ASSERT_EQ(dest_word().byte(5), 5);
}
<|endoftext|>