<commit_before>/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/audio_coding/neteq4/decision_logic_normal.h"

#include <assert.h>

#include <algorithm>

#include "webrtc/modules/audio_coding/neteq4/buffer_level_filter.h"
#include "webrtc/modules/audio_coding/neteq4/decoder_database.h"
#include "webrtc/modules/audio_coding/neteq4/delay_manager.h"
#include "webrtc/modules/audio_coding/neteq4/expand.h"
#include "webrtc/modules/audio_coding/neteq4/packet_buffer.h"
#include "webrtc/modules/audio_coding/neteq4/sync_buffer.h"
#include "webrtc/modules/interface/module_common_types.h"

namespace webrtc {

Operations DecisionLogicNormal::GetDecisionSpecialized(
    const SyncBuffer& sync_buffer,
    const Expand& expand,
    int decoder_frame_length,
    const RTPHeader* packet_header,
    Modes prev_mode,
    bool play_dtmf,
    bool* reset_decoder) {
  assert(playout_mode_ == kPlayoutOn || playout_mode_ == kPlayoutStreaming);
  // Guard for errors, to avoid getting stuck in error mode.
  if (prev_mode == kModeError) {
    if (!packet_header) {
      return kExpand;
    } else {
      return kUndefined;  // Use kUndefined to flag for a reset.
    }
  }

  uint32_t target_timestamp = sync_buffer.end_timestamp();
  uint32_t available_timestamp = 0;
  int is_cng_packet = 0;
  if (packet_header) {
    available_timestamp = packet_header->timestamp;
    is_cng_packet =
        decoder_database_->IsComfortNoise(packet_header->payloadType);
  }

  if (is_cng_packet) {
    return CngOperation(prev_mode, target_timestamp, available_timestamp);
  }

  // Handle the case with no packet at all available (except maybe DTMF).
  if (!packet_header) {
    return NoPacket(play_dtmf);
  }

  // If the expand period was very long, reset NetEQ since it is likely that the
  // sender was restarted.
  if (num_consecutive_expands_ > kReinitAfterExpands) {
    *reset_decoder = true;
    return kNormal;
  }

  // Check if the required packet is available.
  if (target_timestamp == available_timestamp) {
    return ExpectedPacketAvailable(prev_mode, play_dtmf);
  } else if (available_timestamp > target_timestamp) {
    // TODO(hlundin): Consider wrap-around too?
    return FuturePacketAvailable(sync_buffer, expand, decoder_frame_length,
                                 prev_mode, target_timestamp,
                                 available_timestamp, play_dtmf);
  } else {
    // This implies that available_timestamp < target_timestamp, which can
    // happen when a new stream or codec is received. Signal for a reset.
    return kUndefined;
  }
}

Operations DecisionLogicNormal::CngOperation(Modes prev_mode,
                                             uint32_t target_timestamp,
                                             uint32_t available_timestamp) {
  // Signed difference between target and available timestamp.
  int32_t timestamp_diff = (generated_noise_samples_ + target_timestamp) -
      available_timestamp;
  int32_t optimal_level_samp =
      (delay_manager_->TargetLevel() * packet_length_samples_) >> 8;
  int32_t excess_waiting_time_samp = -timestamp_diff - optimal_level_samp;

  if (excess_waiting_time_samp > optimal_level_samp / 2) {
    // The waiting time for this packet will be longer than 1.5
    // times the wanted buffer delay. Advance the clock to cut
    // waiting time down to the optimal.
    generated_noise_samples_ += excess_waiting_time_samp;
    timestamp_diff += excess_waiting_time_samp;
  }

  if (timestamp_diff < 0 && prev_mode == kModeRfc3389Cng) {
    // Not time to play this packet yet. Wait another round before using this
    // packet. Keep on playing CNG from previous CNG parameters.
    return kRfc3389CngNoPacket;
  } else {
    // Otherwise, go for the CNG packet now.
    return kRfc3389Cng;
  }
}

Operations DecisionLogicNormal::NoPacket(bool play_dtmf) {
  if (cng_state_ == kCngRfc3389On) {
    // Keep on playing comfort noise.
    return kRfc3389CngNoPacket;
  } else if (cng_state_ == kCngInternalOn) {
    // Keep on playing codec internal comfort noise.
    return kCodecInternalCng;
  } else if (play_dtmf) {
    return kDtmf;
  } else {
    // Nothing to play, do expand.
    return kExpand;
  }
}

Operations DecisionLogicNormal::ExpectedPacketAvailable(Modes prev_mode,
                                                        bool play_dtmf) {
  if (prev_mode != kModeExpand && !play_dtmf) {
    // Check criterion for time-stretching.
    int low_limit, high_limit;
    delay_manager_->BufferLimits(&low_limit, &high_limit);
    if ((buffer_level_filter_->filtered_current_level() >= high_limit &&
        TimescaleAllowed()) ||
        buffer_level_filter_->filtered_current_level() >= high_limit << 2) {
      // Buffer level higher than limit and time-scaling allowed,
      // or buffer level really high.
      return kAccelerate;
    } else if ((buffer_level_filter_->filtered_current_level() < low_limit)
        && TimescaleAllowed()) {
      return kPreemptiveExpand;
    }
  }
  return kNormal;
}

Operations DecisionLogicNormal::FuturePacketAvailable(
    const SyncBuffer& sync_buffer,
    const Expand& expand,
    int decoder_frame_length,
    Modes prev_mode,
    uint32_t target_timestamp,
    uint32_t available_timestamp,
    bool play_dtmf) {
  // Required packet is not available, but a future packet is.
  // Check if we should continue with an ongoing expand because the new packet
  // is too far into the future.
  uint32_t timestamp_leap = available_timestamp - target_timestamp;
  if ((prev_mode == kModeExpand) &&
      !ReinitAfterExpands(timestamp_leap) &&
      !MaxWaitForPacket() &&
      PacketTooEarly(timestamp_leap) &&
      UnderTargetLevel()) {
    if (play_dtmf) {
      // Still have DTMF to play, so do not do expand.
      return kDtmf;
    } else {
      // Nothing to play.
      return kExpand;
    }
  }

  const int samples_left = static_cast<int>(sync_buffer.FutureLength() -
      expand.overlap_length());
  const int cur_size_samples = samples_left +
      packet_buffer_.NumPacketsInBuffer() * decoder_frame_length;

  // If previous was comfort noise, then no merge is needed.
  if (prev_mode == kModeRfc3389Cng ||
      prev_mode == kModeCodecInternalCng) {
    // Keep the same delay as before the CNG (or maximum 70 ms in buffer as
    // safety precaution), but make sure that the number of samples in buffer
    // is no higher than 4 times the optimal level. (Note that TargetLevel()
    // is in Q8.)
    int32_t timestamp_diff = (generated_noise_samples_ + target_timestamp) -
        available_timestamp;
    if (timestamp_diff >= 0 ||
        cur_size_samples >
        4 * ((delay_manager_->TargetLevel() * packet_length_samples_) >> 8)) {
      // Time to play this new packet.
      return kNormal;
    } else {
      // Too early to play this new packet; keep on playing comfort noise.
      if (prev_mode == kModeRfc3389Cng) {
        return kRfc3389CngNoPacket;
      } else {  // prevPlayMode == kModeCodecInternalCng.
        return kCodecInternalCng;
      }
    }
  }
  // Do not merge unless we have done an expand before.
  // (Convert kAllowMergeWithoutExpand from ms to samples by multiplying with
  // fs_mult_ * 8 = fs / 1000.)
  if (prev_mode == kModeExpand ||
      (decoder_frame_length < output_size_samples_ &&
       cur_size_samples > kAllowMergeWithoutExpandMs * fs_mult_ * 8)) {
    return kMerge;
  } else if (play_dtmf) {
    // Play DTMF instead of expand.
    return kDtmf;
  } else {
    return kExpand;
  }
}

bool DecisionLogicNormal::UnderTargetLevel() const {
  return buffer_level_filter_->filtered_current_level() <=
      delay_manager_->TargetLevel();
}

bool DecisionLogicNormal::ReinitAfterExpands(uint32_t timestamp_leap) const {
  return timestamp_leap >=
      static_cast<uint32_t>(output_size_samples_ * kReinitAfterExpands);
}

bool DecisionLogicNormal::PacketTooEarly(uint32_t timestamp_leap) const {
  return timestamp_leap >
      static_cast<uint32_t>(output_size_samples_ * num_consecutive_expands_);
}

bool DecisionLogicNormal::MaxWaitForPacket() const {
  return num_consecutive_expands_ >= kMaxWaitForPacket;
}

}  // namespace webrtc
<commit_msg>Accounting for wrap-around of timestamps.<commit_after>/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/audio_coding/neteq4/decision_logic_normal.h"

#include <assert.h>

#include <algorithm>

#include "webrtc/modules/audio_coding/neteq4/buffer_level_filter.h"
#include "webrtc/modules/audio_coding/neteq4/decoder_database.h"
#include "webrtc/modules/audio_coding/neteq4/delay_manager.h"
#include "webrtc/modules/audio_coding/neteq4/expand.h"
#include "webrtc/modules/audio_coding/neteq4/packet_buffer.h"
#include "webrtc/modules/audio_coding/neteq4/sync_buffer.h"
#include "webrtc/modules/interface/module_common_types.h"

namespace webrtc {

Operations DecisionLogicNormal::GetDecisionSpecialized(
    const SyncBuffer& sync_buffer,
    const Expand& expand,
    int decoder_frame_length,
    const RTPHeader* packet_header,
    Modes prev_mode,
    bool play_dtmf,
    bool* reset_decoder) {
  assert(playout_mode_ == kPlayoutOn || playout_mode_ == kPlayoutStreaming);
  // Guard for errors, to avoid getting stuck in error mode.
  if (prev_mode == kModeError) {
    if (!packet_header) {
      return kExpand;
    } else {
      return kUndefined;  // Use kUndefined to flag for a reset.
    }
  }

  uint32_t target_timestamp = sync_buffer.end_timestamp();
  uint32_t available_timestamp = 0;
  int is_cng_packet = 0;
  if (packet_header) {
    available_timestamp = packet_header->timestamp;
    is_cng_packet =
        decoder_database_->IsComfortNoise(packet_header->payloadType);
  }

  if (is_cng_packet) {
    return CngOperation(prev_mode, target_timestamp, available_timestamp);
  }

  // Handle the case with no packet at all available (except maybe DTMF).
  if (!packet_header) {
    return NoPacket(play_dtmf);
  }

  // If the expand period was very long, reset NetEQ since it is likely that the
  // sender was restarted.
  if (num_consecutive_expands_ > kReinitAfterExpands) {
    *reset_decoder = true;
    return kNormal;
  }

  // Check if the required packet is available.
  if (target_timestamp == available_timestamp) {
    return ExpectedPacketAvailable(prev_mode, play_dtmf);
  } else if (IsNewerTimestamp(available_timestamp, target_timestamp)) {
    return FuturePacketAvailable(sync_buffer, expand, decoder_frame_length,
                                 prev_mode, target_timestamp,
                                 available_timestamp, play_dtmf);
  } else {
    // This implies that available_timestamp < target_timestamp, which can
    // happen when a new stream or codec is received. Signal for a reset.
    return kUndefined;
  }
}

Operations DecisionLogicNormal::CngOperation(Modes prev_mode,
                                             uint32_t target_timestamp,
                                             uint32_t available_timestamp) {
  // Signed difference between target and available timestamp.
  int32_t timestamp_diff = (generated_noise_samples_ + target_timestamp) -
      available_timestamp;
  int32_t optimal_level_samp =
      (delay_manager_->TargetLevel() * packet_length_samples_) >> 8;
  int32_t excess_waiting_time_samp = -timestamp_diff - optimal_level_samp;

  if (excess_waiting_time_samp > optimal_level_samp / 2) {
    // The waiting time for this packet will be longer than 1.5
    // times the wanted buffer delay. Advance the clock to cut
    // waiting time down to the optimal.
    generated_noise_samples_ += excess_waiting_time_samp;
    timestamp_diff += excess_waiting_time_samp;
  }

  if (timestamp_diff < 0 && prev_mode == kModeRfc3389Cng) {
    // Not time to play this packet yet. Wait another round before using this
    // packet. Keep on playing CNG from previous CNG parameters.
    return kRfc3389CngNoPacket;
  } else {
    // Otherwise, go for the CNG packet now.
    return kRfc3389Cng;
  }
}

Operations DecisionLogicNormal::NoPacket(bool play_dtmf) {
  if (cng_state_ == kCngRfc3389On) {
    // Keep on playing comfort noise.
    return kRfc3389CngNoPacket;
  } else if (cng_state_ == kCngInternalOn) {
    // Keep on playing codec internal comfort noise.
    return kCodecInternalCng;
  } else if (play_dtmf) {
    return kDtmf;
  } else {
    // Nothing to play, do expand.
    return kExpand;
  }
}

Operations DecisionLogicNormal::ExpectedPacketAvailable(Modes prev_mode,
                                                        bool play_dtmf) {
  if (prev_mode != kModeExpand && !play_dtmf) {
    // Check criterion for time-stretching.
    int low_limit, high_limit;
    delay_manager_->BufferLimits(&low_limit, &high_limit);
    if ((buffer_level_filter_->filtered_current_level() >= high_limit &&
        TimescaleAllowed()) ||
        buffer_level_filter_->filtered_current_level() >= high_limit << 2) {
      // Buffer level higher than limit and time-scaling allowed,
      // or buffer level really high.
      return kAccelerate;
    } else if ((buffer_level_filter_->filtered_current_level() < low_limit)
        && TimescaleAllowed()) {
      return kPreemptiveExpand;
    }
  }
  return kNormal;
}

Operations DecisionLogicNormal::FuturePacketAvailable(
    const SyncBuffer& sync_buffer,
    const Expand& expand,
    int decoder_frame_length,
    Modes prev_mode,
    uint32_t target_timestamp,
    uint32_t available_timestamp,
    bool play_dtmf) {
  // Required packet is not available, but a future packet is.
  // Check if we should continue with an ongoing expand because the new packet
  // is too far into the future.
  uint32_t timestamp_leap = available_timestamp - target_timestamp;
  if ((prev_mode == kModeExpand) &&
      !ReinitAfterExpands(timestamp_leap) &&
      !MaxWaitForPacket() &&
      PacketTooEarly(timestamp_leap) &&
      UnderTargetLevel()) {
    if (play_dtmf) {
      // Still have DTMF to play, so do not do expand.
      return kDtmf;
    } else {
      // Nothing to play.
      return kExpand;
    }
  }

  const int samples_left = static_cast<int>(sync_buffer.FutureLength() -
      expand.overlap_length());
  const int cur_size_samples = samples_left +
      packet_buffer_.NumPacketsInBuffer() * decoder_frame_length;

  // If previous was comfort noise, then no merge is needed.
  if (prev_mode == kModeRfc3389Cng ||
      prev_mode == kModeCodecInternalCng) {
    // Keep the same delay as before the CNG (or maximum 70 ms in buffer as
    // safety precaution), but make sure that the number of samples in buffer
    // is no higher than 4 times the optimal level. (Note that TargetLevel()
    // is in Q8.)
    int32_t timestamp_diff = (generated_noise_samples_ + target_timestamp) -
        available_timestamp;
    if (timestamp_diff >= 0 ||
        cur_size_samples >
        4 * ((delay_manager_->TargetLevel() * packet_length_samples_) >> 8)) {
      // Time to play this new packet.
      return kNormal;
    } else {
      // Too early to play this new packet; keep on playing comfort noise.
      if (prev_mode == kModeRfc3389Cng) {
        return kRfc3389CngNoPacket;
      } else {  // prevPlayMode == kModeCodecInternalCng.
        return kCodecInternalCng;
      }
    }
  }
  // Do not merge unless we have done an expand before.
  // (Convert kAllowMergeWithoutExpand from ms to samples by multiplying with
  // fs_mult_ * 8 = fs / 1000.)
  if (prev_mode == kModeExpand ||
      (decoder_frame_length < output_size_samples_ &&
       cur_size_samples > kAllowMergeWithoutExpandMs * fs_mult_ * 8)) {
    return kMerge;
  } else if (play_dtmf) {
    // Play DTMF instead of expand.
    return kDtmf;
  } else {
    return kExpand;
  }
}

bool DecisionLogicNormal::UnderTargetLevel() const {
  return buffer_level_filter_->filtered_current_level() <=
      delay_manager_->TargetLevel();
}

bool DecisionLogicNormal::ReinitAfterExpands(uint32_t timestamp_leap) const {
  return timestamp_leap >=
      static_cast<uint32_t>(output_size_samples_ * kReinitAfterExpands);
}

bool DecisionLogicNormal::PacketTooEarly(uint32_t timestamp_leap) const {
  return timestamp_leap >
      static_cast<uint32_t>(output_size_samples_ * num_consecutive_expands_);
}

bool DecisionLogicNormal::MaxWaitForPacket() const {
  return num_consecutive_expands_ >= kMaxWaitForPacket;
}

}  // namespace webrtc
<|endoftext|>


<commit_before>// -----------------------------------------------------------------------------
// Copyright  : (C) 2014 Andreas-C. Bernstein
// License    : MIT (see the file LICENSE)
// Maintainer : Andreas-C. Bernstein <andreas.bernstein@uni-weimar.de>
// Stability  : experimental
//
// Renderer
// -----------------------------------------------------------------------------

#include "renderer.hpp"

Renderer::Renderer(Scene const& scene, unsigned w, unsigned h, std::string const& file)
  : scene_(scene)
  , width_(w)
  , height_(h)
  , colorbuffer_(w*h, Color(0.0, 0.0, 0.0))
  , filename_(file)
  , ppm_(width_, height_)
{}

void Renderer::render()
{
  const std::size_t checkersize = 20;
  std::cout << "Achtung Achtung: Ueberschreibe scene_\n";
  scene_.shapes.push_back(std::make_shared<Sphere>(Material(), "gugel", glm::vec3(0,0,-3.0), 1.0));

  for (unsigned y = 0; y < height_; ++y) {
    for (unsigned x = 0; x < width_; ++x) {
      Pixel p(x,y);
      Ray ray = scene_.camera.calc_eye_ray(x,y,height_,width_);
//      glm::vec3 origin{float(x)*2.0/float(width_) - 1.0,float(y)*2.0/float(height_) - 1.0,0};
//      glm::vec3 direction{0,0,-1};
//      Ray ray{origin, direction};

      float nearest_t = 10000.0;
      Shape* closest = nullptr;
      for (auto const& shape : scene_.shapes) {
        float t = 0.0;
        bool hit = shape->intersect(ray, t);
        if (hit && 0 < t && t < nearest_t) {
          nearest_t = t;
          closest = shape.get();
        }
      }

      // p.color = raytrace(ray, 3);
      if ( closest ) {
        // p.color = normal * 0.5f + 0.5f:
        p.color = Color(1.0,1.0,1.0);
      } else {
        p.color = Color(0,0,0);
      }

      write(p);
    }
  }
  ppm_.save(filename_);
}

void Renderer::write(Pixel const& p)
{
  // flip pixels, because of opengl glDrawPixels
  size_t buf_pos = (width_*p.y + p.x);
  if (buf_pos >= colorbuffer_.size() || (int)buf_pos < 0) {
    std::cerr << "Fatal Error Renderer::write(Pixel p) : "
      << "pixel out of ppm_ : "
      << (int)p.x << "," << (int)p.y
      << std::endl;
  } else {
    colorbuffer_[buf_pos] = p.color;
  }

  ppm_.write(p);
}
<commit_msg>normale in renderer anhand von farben getestet, kugel vrezieht sich,wenn sie aus dem ursprung verschoben wird<commit_after>// -----------------------------------------------------------------------------
// Copyright  : (C) 2014 Andreas-C. Bernstein
// License    : MIT (see the file LICENSE)
// Maintainer : Andreas-C. Bernstein <andreas.bernstein@uni-weimar.de>
// Stability  : experimental
//
// Renderer
// -----------------------------------------------------------------------------

#include "renderer.hpp"

Renderer::Renderer(Scene const& scene, unsigned w, unsigned h, std::string const& file)
  : scene_(scene)
  , width_(w)
  , height_(h)
  , colorbuffer_(w*h, Color(0.0, 0.0, 0.0))
  , filename_(file)
  , ppm_(width_, height_)
{}

void Renderer::render()
{
  const std::size_t checkersize = 20;
  std::cout << "Achtung Achtung: Ueberschreibe scene_\n";
  scene_.shapes.push_back(std::make_shared<Sphere>(Material(), "gugel", glm::vec3(0,0,-3.0), 1.0));

  for (unsigned y = 0; y < height_; ++y) {
    for (unsigned x = 0; x < width_; ++x) {
      Pixel p(x,y);
      Ray ray = scene_.camera.calc_eye_ray(x,y,height_,width_);
//      glm::vec3 origin{float(x)*2.0/float(width_) - 1.0,float(y)*2.0/float(height_) - 1.0,0};
//      glm::vec3 direction{0,0,-1};
//      Ray ray{origin, direction};

      float nearest_t = 10000.0;
      Shape* closest = nullptr;
      float t = 0.0;
      for (auto const& shape : scene_.shapes) {
        bool hit = shape->intersect(ray, t);
        if (hit && 0 < t && t < nearest_t) {
          nearest_t = t;
          closest = shape.get();
        }
      }

      glm::vec3 normal{ray.origin_ + ray.direction_*t};
      normal.x = normal.x-0;
      normal.y = normal.y-0;
      normal.z = normal.z+3;
      normal = glm::normalize(normal);
      auto tmpN = normal * 0.5f + 0.5f;

      // p.color = raytrace(ray, 3);
      if ( closest ) {
        p.color = Color(tmpN.x,tmpN.y,tmpN.z);
        //p.color = Color(1.0,1.0,1.0);
      } else {
        p.color = Color(0,0,0);
      }

      write(p);
    }
  }
  ppm_.save(filename_);
}

void Renderer::write(Pixel const& p)
{
  // flip pixels, because of opengl glDrawPixels
  size_t buf_pos = (width_*p.y + p.x);
  if (buf_pos >= colorbuffer_.size() || (int)buf_pos < 0) {
    std::cerr << "Fatal Error Renderer::write(Pixel p) : "
      << "pixel out of ppm_ : "
      << (int)p.x << "," << (int)p.y
      << std::endl;
  } else {
    colorbuffer_[buf_pos] = p.color;
  }

  ppm_.write(p);
}
<|endoftext|>


<commit_before>#include "SPHERES.H"

#include "DRAW.H"
#include "CONTROL.H"
#include "SPECIFIC.H"
#include "GETSTUFF.H"
#include "GTEREG.H"
#include "LOAD_LEV.H"
#include "SETUP.H"
#include "MATHS.H"
#include <assert.h>

int GetSpheres(struct ITEM_INFO* item, struct SPHERE* sptr, int worldspace)
{
	UNIMPLEMENTED();
	return 0;
}

void GetJointAbsPosition(struct ITEM_INFO* item, struct PHD_VECTOR* pos, int joint)//8E860(<) 908A4(<) (F)
{
	struct object_info* object;//s1
	short* frames[2];//var_38
	int rate;//var_30
	int frac;//s0
	long* bone;//s0
	short* frameptr;//var_2C
	short* frameptr2;//var_28
	short* item_data;
	int t0;
	int t1;
	int t2;
	struct MATRIX3D* mat;//var_24

	object = &objects[item->object_number];
	mat = Matrix;
	frac = GetFrames(item, frames, &rate);
	mPushUnitMatrix();
	mSetTrans(0, 0, 0);
	mRotYXZ(item->pos.y_rot, item->pos.x_rot, item->pos.z_rot);

	item_data = (short*)item->data;
	bone = &bones[object->bone_index];

	if (frac == 0)
	{
		frameptr = &frames[0][9];
		mTranslateXYZ(frames[0][6], frames[0][7], frames[0][8]);
		mRotSuperPackedYXZ(&frameptr, 0);

		if (joint > 0)
		{
			//loc_8E92C
			do
			{
				if ((*bone & 1))
				{
					mPopMatrix();
				}//loc_8E94C

				if ((*bone & 2))
				{
					mPushMatrix();
				}
				//loc_8E95C
				mTranslateXYZ(bone[1], bone[2], bone[3]);
				mRotSuperPackedYXZ(&frameptr, 0);

				if (item_data != NULL && (*bone & 0x1C))
				{
					if ((*bone & 0x8))
					{
						mRotY(*item_data++);
					}

					//loc_8E9A0
					if ((*bone & 0x4))
					{
						mRotX(*item_data++);
					}

					//loc_8E9B8
					if ((*bone & 0x10))
					{
						mRotZ(*item_data++);
					}
				}

				bone += 4;

			} while (--joint);
		}
		//loc_8E9D8
		mTranslateXYZ(pos->x, pos->y, pos->z);///@FIXME reporting bad matrix here.
	}
	else
	{
		//Math functions not impl
		assert(0);
#if 0
		//loc_8E9EC
		//a2 = &iMatrixStack[16];
		InitInterpolation(frac, rate, &iMatrixStack[16]);
		//v1 = frames[0]
		//t0 = frames[1]

		//v0 = &frames[0][9]
		frameptr = &frames[0][9];

		//v0 = &frames[1][9]
		iTranslateXYZ2(frames[0][6], frames[0][7], frames[0][8], frames[1][6], frames[1][7], frames[1][8]);
		mRotSuperPackedYXZ(&frameptr, 0);
		//iRotSuperPackedYXZ(&frameptr + 1, 0);

		//s1 = joint
		if (joint > 0)
		{
			//loc_8EA5C
			do
			{
				if ((*bone & 1))
				{
					iPopMatrix();
				}//loc_8EA7C

				if ((*bone & 2))
				{
					iPushMatrix();
				}
				//loc_8EA8C
				iTranslateXYZ(bone[1], bone[2], bone[3]);
				mRotSuperPackedYXZ(&frameptr, 0);
				iRotSuperPackedYXZ(&frameptr2, 0);

				if (item->data != NULL && (*bone & 0x1C) && (*bone & 0x8))
				{
					mRotY(*item_data);
					iRotY(*item_data++);
				}//loc_8EAE8

				if ((*bone & 0x4))
				{
					mRotX(*item_data);
					iRotX(*item_data++);
				}

				if ((*bone & 0x10))
				{
					mRotZ(*item_data);
					iRotZ(*item_data++);
				}
				bone += 4;
			} while (joint--);
		}//loc_8EB38
		iTranslateXYZ(pos->x, pos->y, pos->z);
		InterpolateMatrix();
#endif
	}

	pos->x = item->pos.x_pos + TRX;
	pos->y = item->pos.y_pos + TRY;
	pos->z = item->pos.z_pos + TRZ;

	Matrix = mat;
	mCopyMatrix(mat);

	return;
}

int IsRoomOutside(long x, long y, long z)//(F)
{
	int v1;
	int a0;
	int v0;
	short roomOffset;//v0
	int t0;
	struct room_info* r;//s1
	short room_number;
	struct FLOOR_INFO* floor;//s0
	int h;//v1
	int c;//v0
	int i;
	//s3 = x
	//s2 = y
	//s4 = z

	v1 = x >> 12;
	a0 = z >> 12;

	v0 = v1 << 3;
	v0 -= v1;
	v0 <<= 2;
	v0 -= v1;
	v0 += a0;
	//v1 = OutsideRoomOffsets
	if (x < 0 && z < 0)
	{
		return -2;
	}

	//loc_8EF54
	roomOffset = OutsideRoomOffsets[v0];

	if (roomOffset == -1)
	{
		return -2;
	}

	t0 = roomOffset & 0x7FFF;

	if (roomOffset < 0)
	{
		r = &room[t0];

		if (y < r->maxceiling)
		{
			return -2;
		}

		if (r->minfloor < y)
		{
			return -2;
		}

		if (z < (r->z + 1024))
		{
			return -2;
		}

		if (r->z + ((r->x_size - 1) << 10) < z)
		{
			return -2;
		}

		if (x < (r->x + 1024))
		{
			return -2;
		}

		if (r->x + ((r->y_size - 1) << 10) < x)
		{
			return -2;
		}

		room_number = t0;
		IsRoomOutsideNo = room_number;
		floor = GetFloor(x, y, z, &room_number);
		h = GetHeight(floor, x, y, z);

		if (h == -32512 || h < y)
		{
			return -2;
		}

		c = GetCeiling(floor, x, y, z);

		if (y < c)
		{
			return -2;
		}

		if ((r->flags & (RF_FILL_WATER | RF_WIND_BLOWS_PONYTAIL)))
		{
			return 1;
		}

		return -3;
	}
	else
	{
		//loc_8EFF4
		if (OutsideRoomTable[roomOffset] == -1)
		{
			return -2;
		}

		//loc_8F000
		i = 0;
		while(i++)
		{
			r = &room[OutsideRoomTable[roomOffset]];

			if (y > r->maxceiling && r->minfloor > y &&
				z > (r->z + 1024) && r->z + ((r->x_size - 1) << 10) > z &&
				x > (r->x + 1024) && r->x + ((r->y_size - 1) << 10) > x)
			{
				//loc_8F07C
				IsRoomOutsideNo = OutsideRoomTable[roomOffset];
				room_number = IsRoomOutsideNo;
				floor = GetFloor(x, y, z, &room_number);
				h = GetHeight(floor, x, y, z);

				if (h == -32512 || h < y)
				{
					return -2;
				}

				c = GetCeiling(floor, x, y, z);

				if (y < c)
				{
					return -2;
				}

				if (r->flags & (RF_WIND_BLOWS_PONYTAIL | RF_FILL_WATER))
				{
					return 1;
				}

				return -3;

			}//loc_8F104

			if (OutsideRoomTable[roomOffset + i] == -1)
			{
				return -2;
			}
		}
	}

	return 0;
}<commit_msg>[Specific-PSXPC_N] Fixes for IsRoomOutside<commit_after>#include "SPHERES.H"

#include "DRAW.H"
#include "CONTROL.H"
#include "SPECIFIC.H"
#include "GETSTUFF.H"
#include "GTEREG.H"
#include "LOAD_LEV.H"
#include "SETUP.H"
#include "MATHS.H"
#include <assert.h>

int GetSpheres(struct ITEM_INFO* item, struct SPHERE* sptr, int worldspace)
{
	UNIMPLEMENTED();
	return 0;
}

void GetJointAbsPosition(struct ITEM_INFO* item, struct PHD_VECTOR* pos, int joint)//8E860(<) 908A4(<) (F)
{
	struct object_info* object;//s1
	short* frames[2];//var_38
	int rate;//var_30
	int frac;//s0
	long* bone;//s0
	short* frameptr;//var_2C
	short* frameptr2;//var_28
	short* item_data;
	int t0;
	int t1;
	int t2;
	struct MATRIX3D* mat;//var_24

	object = &objects[item->object_number];
	mat = Matrix;
	frac = GetFrames(item, frames, &rate);
	mPushUnitMatrix();
	mSetTrans(0, 0, 0);
	mRotYXZ(item->pos.y_rot, item->pos.x_rot, item->pos.z_rot);

	item_data = (short*)item->data;
	bone = &bones[object->bone_index];

	if (frac == 0)
	{
		frameptr = &frames[0][9];
		mTranslateXYZ(frames[0][6], frames[0][7], frames[0][8]);
		mRotSuperPackedYXZ(&frameptr, 0);

		if (joint > 0)
		{
			//loc_8E92C
			do
			{
				if ((*bone & 1))
				{
					mPopMatrix();
				}//loc_8E94C

				if ((*bone & 2))
				{
					mPushMatrix();
				}
				//loc_8E95C
				mTranslateXYZ(bone[1], bone[2], bone[3]);
				mRotSuperPackedYXZ(&frameptr, 0);

				if (item_data != NULL && (*bone & 0x1C))
				{
					if ((*bone & 0x8))
					{
						mRotY(*item_data++);
					}

					//loc_8E9A0
					if ((*bone & 0x4))
					{
						mRotX(*item_data++);
					}

					//loc_8E9B8
					if ((*bone & 0x10))
					{
						mRotZ(*item_data++);
					}
				}

				bone += 4;

			} while (--joint);
		}
		//loc_8E9D8
		mTranslateXYZ(pos->x, pos->y, pos->z);///@FIXME reporting bad matrix here.
	}
	else
	{
		//Math functions not impl
		assert(0);
#if 0
		//loc_8E9EC
		//a2 = &iMatrixStack[16];
		InitInterpolation(frac, rate, &iMatrixStack[16]);
		//v1 = frames[0]
		//t0 = frames[1]

		//v0 = &frames[0][9]
		frameptr = &frames[0][9];

		//v0 = &frames[1][9]
		iTranslateXYZ2(frames[0][6], frames[0][7], frames[0][8], frames[1][6], frames[1][7], frames[1][8]);
		mRotSuperPackedYXZ(&frameptr, 0);
		//iRotSuperPackedYXZ(&frameptr + 1, 0);

		//s1 = joint
		if (joint > 0)
		{
			//loc_8EA5C
			do
			{
				if ((*bone & 1))
				{
					iPopMatrix();
				}//loc_8EA7C

				if ((*bone & 2))
				{
					iPushMatrix();
				}
				//loc_8EA8C
				iTranslateXYZ(bone[1], bone[2], bone[3]);
				mRotSuperPackedYXZ(&frameptr, 0);
				iRotSuperPackedYXZ(&frameptr2, 0);

				if (item->data != NULL && (*bone & 0x1C) && (*bone & 0x8))
				{
					mRotY(*item_data);
					iRotY(*item_data++);
				}//loc_8EAE8

				if ((*bone & 0x4))
				{
					mRotX(*item_data);
					iRotX(*item_data++);
				}

				if ((*bone & 0x10))
				{
					mRotZ(*item_data);
					iRotZ(*item_data++);
				}
				bone += 4;
			} while (joint--);
		}//loc_8EB38
		iTranslateXYZ(pos->x, pos->y, pos->z);
		InterpolateMatrix();
#endif
	}

	pos->x = item->pos.x_pos + TRX;
	pos->y = item->pos.y_pos + TRY;
	pos->z = item->pos.z_pos + TRZ;

	Matrix = mat;
	mCopyMatrix(mat);

	return;
}

int IsRoomOutside(long x, long y, long z)//(F)
{
	int v1;
	int a0;
	int v0;
	short roomOffset;//v0
	int t0;
	struct room_info* r;//s1
	short room_number;
	struct FLOOR_INFO* floor;//s0
	int h;//v1
	int c;//v0
	int i;
	//s3 = x
	//s2 = y
	//s4 = z

	v1 = x >> 12;
	a0 = z >> 12;

	v0 = v1 << 3;
	v0 -= v1;
	v0 <<= 2;
	v0 -= v1;
	v0 += a0;
	//v1 = OutsideRoomOffsets
	if (x < 0 && z < 0)
	{
		return -2;
	}

	//loc_8EF54
	roomOffset = OutsideRoomOffsets[v0];

	if (roomOffset == -1)
	{
		return -2;
	}

	t0 = roomOffset & 0x7FFF;

	if (roomOffset < 0)
	{
		r = &room[t0];

		if (y < r->maxceiling)
		{
			return -2;
		}

		if (r->minfloor < y)
		{
			return -2;
		}

		if (z < (r->z + 1024))
		{
			return -2;
		}

		if (r->z + ((r->x_size - 1) << 10) < z)
		{
			return -2;
		}

		if (x < (r->x + 1024))
		{
			return -2;
		}

		if (r->x + ((r->y_size - 1) << 10) < x)
		{
			return -2;
		}

		room_number = t0;
		IsRoomOutsideNo = room_number;
		floor = GetFloor(x, y, z, &room_number);
		h = GetHeight(floor, x, y, z);

		if (h == -32512 || h < y)
		{
			return -2;
		}

		c = GetCeiling(floor, x, y, z);

		if (y < c)
		{
			return -2;
		}

		if ((r->flags & (RF_FILL_WATER | RF_WIND_BLOWS_PONYTAIL)))
		{
			return 1;
		}

		return -3;
	}
	else
	{
		//loc_8EFF4
		if (OutsideRoomTable[roomOffset] == -1)
		{
			return -2;
		}

		//loc_8F000
		for(i = 0; ; i++)
		{
			r = &room[OutsideRoomTable[roomOffset + i]];

			if (y > r->maxceiling && r->minfloor > y &&
				z > (r->z + 1024) && r->z + ((r->x_size - 1) << 10) > z &&
				x > (r->x + 1024) && r->x + ((r->y_size - 1) << 10) > x)
			{
				//loc_8F07C
				IsRoomOutsideNo = OutsideRoomTable[roomOffset + i];
				room_number = IsRoomOutsideNo;
				floor = GetFloor(x, y, z, &room_number);
				h = GetHeight(floor, x, y, z);

				if (h == -32512 || h < y)
				{
					return -2;
				}

				c = GetCeiling(floor, x, y, z);

				if (y < c)
				{
					return -2;
				}

				if (r->flags & (RF_WIND_BLOWS_PONYTAIL | RF_FILL_WATER))
				{
					return 1;
				}

				return -3;

			}//loc_8F104

			if (OutsideRoomTable[roomOffset + i] == -1)
			{
				return -2;
			}
		}
	}

	return 0;
}<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact:  Qt Software Information (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
**************************************************************************/

#include "debuggeractions.h"

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

#include <QtCore/QSettings>
#include <QtGui/QAction>
#include <QtGui/QAbstractButton>
#include <QtGui/QRadioButton>
#include <QtGui/QCheckBox>
#include <QtGui/QLineEdit>

namespace Debugger {
namespace Internal {

//////////////////////////////////////////////////////////////////////////
//
// QtcSettingsItem
//
//////////////////////////////////////////////////////////////////////////

QtcSettingsItem::QtcSettingsItem(QObject *parent)
  : QObject(parent)
{
    m_action = new QAction(this);
    connect(m_action, SIGNAL(triggered(bool)), this, SLOT(actionTriggered(bool)));
}

QVariant QtcSettingsItem::value() const
{
    return m_value;
}

void QtcSettingsItem::setValue(const QVariant &value, bool doemit)
{
    if (value != m_value) {
        m_value = value;
        if (m_action->isCheckable())
            m_action->setChecked(m_value.toBool());
        if (doemit) {
            emit valueChanged(m_value);
            emit boolValueChanged(m_value.toBool());
            emit stringValueChanged(m_value.toString());
        }
    }
}

QVariant QtcSettingsItem::defaultValue() const
{
    return m_defaultValue;
}

void QtcSettingsItem::setDefaultValue(const QVariant &value)
{
    m_defaultValue = value;
}

QString QtcSettingsItem::settingsKey() const
{
    return m_settingsKey;
}

void QtcSettingsItem::setSettingsKey(const QString &key)
{
    m_settingsKey = key;
}

void QtcSettingsItem::setSettingsKey(const QString &group, const QString &key)
{
    m_settingsKey = key;
    m_settingsGroup = group;
}

QString QtcSettingsItem::settingsGroup() const
{
    return m_settingsGroup;
}

void QtcSettingsItem::setSettingsGroup(const QString &group)
{
    m_settingsGroup = group;
}

QString QtcSettingsItem::text() const
{
    return m_action->text();
}

void QtcSettingsItem::setText(const QString &value)
{
    if (!value.isEmpty() && !m_textPattern.isEmpty())
        m_action->setText(m_textPattern.arg(value));
    else
        m_action->setText(value);
}

QString QtcSettingsItem::textPattern() const
{
    return m_textPattern;
}

void QtcSettingsItem::setTextPattern(const QString &value)
{
    m_textPattern = value;
}

void QtcSettingsItem::readSettings(QSettings *settings)
{
    if (m_settingsGroup.isEmpty() || m_settingsKey.isEmpty())
        return;
    settings->beginGroup(m_settingsGroup);
    setValue(settings->value(m_settingsKey, m_defaultValue), false);
    qDebug() << "READING: " << m_settingsKey << " -> " << m_value;
    settings->endGroup();
}

void QtcSettingsItem::writeSettings(QSettings *settings)
{
    if (m_settingsGroup.isEmpty() || m_settingsKey.isEmpty())
        return;
    settings->beginGroup(m_settingsGroup);
    settings->setValue(m_settingsKey, m_value);
    qDebug() << "WRITING: " << m_settingsKey << " -> " << m_value;
    settings->endGroup();
}

QAction *QtcSettingsItem::action() const
{
    return m_action;
}

void QtcSettingsItem::connectWidget(QWidget *widget, ApplyMode applyMode)
{
    using namespace Core::Utils;
    //qDebug() << "CONNECT WIDGET " << widget << " TO " << m_settingsKey;
    m_applyModes[widget] = applyMode;
    m_deferedValue = m_value;
    if (QAbstractButton *button = qobject_cast<QAbstractButton *>(widget)) {
        if (button->isCheckable()) {
            button->setChecked(m_value.toBool());
            connect(button, SIGNAL(clicked(bool)),
                this, SLOT(checkableButtonClicked(bool)));
        } else {
            connect(button, SIGNAL(clicked()),
                this, SLOT(uncheckableButtonClicked()));
        }
    } else if (QLineEdit *lineEdit = qobject_cast<QLineEdit *>(widget)) {
        lineEdit->setText(m_value.toString());
        //qDebug() << "SETTING TEXT" << lineEdit->text();
        connect(lineEdit, SIGNAL(editingFinished()),
            this, SLOT(lineEditEditingFinished()));
    } else if (PathChooser *pathChooser = qobject_cast<PathChooser *>(widget)) {
        pathChooser->setPath(m_value.toString());
        connect(pathChooser, SIGNAL(editingFinished()),
            this, SLOT(pathChooserEditingFinished()));
        connect(pathChooser, SIGNAL(browsingFinished()),
            this, SLOT(pathChooserEditingFinished()));
    } else {
        qDebug() << "CANNOT CONNECT WIDGET " << widget;
    }
}

void QtcSettingsItem::apply(QSettings *s)
{
    setValue(m_deferedValue);
    if (s)
        writeSettings(s);
}

void QtcSettingsItem::uncheckableButtonClicked()
{
    QAbstractButton *button = qobject_cast<QAbstractButton *>(sender());
    QTC_ASSERT(button, return);
    qDebug() << "UNCHECKABLE BUTTON: " << sender();
    m_action->trigger();
}

void QtcSettingsItem::checkableButtonClicked(bool)
{
    QAbstractButton *button = qobject_cast<QAbstractButton *>(sender());
    QTC_ASSERT(button, return);
    qDebug() << "CHECKABLE BUTTON: " << sender();
    if (m_applyModes[sender()] == DeferedApply)
        m_deferedValue = button->isChecked();
    else
        setValue(button->isChecked());
}

void QtcSettingsItem::lineEditEditingFinished()
{
    QLineEdit *lineEdit = qobject_cast<QLineEdit *>(sender());
    QTC_ASSERT(lineEdit, return);
    qDebug() << "LINEEDIT: " << sender() << lineEdit->text();
    if (m_applyModes[sender()] == DeferedApply)
        m_deferedValue = lineEdit->text();
    else
        setValue(lineEdit->text());
}

void QtcSettingsItem::pathChooserEditingFinished()
{
    using namespace Core::Utils;
    PathChooser *pathChooser = qobject_cast<PathChooser *>(sender());
    QTC_ASSERT(pathChooser, return);
    qDebug() << "PATHCHOOSER: " << sender() << pathChooser->path();
    if (m_applyModes[sender()] == DeferedApply)
        m_deferedValue = pathChooser->path();
    else
        setValue(pathChooser->path());
}

void QtcSettingsItem::actionTriggered(bool on)
{
    Q_UNUSED(on);
    if (QAction *action = qobject_cast<QAction *>(sender())) {
        if (action->isCheckable())
            setValue(action->isChecked());
    }
}

//////////////////////////////////////////////////////////////////////////
//
// QtcSettingsPool
//
//////////////////////////////////////////////////////////////////////////

QtcSettingsPool::QtcSettingsPool(QObject *parent)
    : QObject(parent)
{}

QtcSettingsPool::~QtcSettingsPool()
{
    qDeleteAll(m_items);
}

void QtcSettingsPool::insertItem(int code, QtcSettingsItem *item)
{
    m_items[code] = item;
}

void QtcSettingsPool::readSettings(QSettings *settings)
{
    foreach (QtcSettingsItem *item, m_items)
        item->readSettings(settings);
}

void QtcSettingsPool::writeSettings(QSettings *settings)
{
    foreach (QtcSettingsItem *item, m_items)
        item->writeSettings(settings);
}

QtcSettingsItem *QtcSettingsPool::item(int code)
{
    QTC_ASSERT(m_items.value(code, 0), return 0);
    return m_items.value(code, 0);
}

QString QtcSettingsPool::dump()
{
    QString out;
    QTextStream ts(&out);
    ts  << "Debugger settings: ";
    foreach (QtcSettingsItem *item, m_items)
        ts << "\n" << item->value().toString();
    return out;
}

//////////////////////////////////////////////////////////////////////////
//
// Debugger specific stuff
//
//////////////////////////////////////////////////////////////////////////

#if 0
    QString dump();

    QString m_gdbCmd;
    QString m_gdbEnv;
    bool m_autoRun;
    bool m_autoQuit;

    bool m_useDumpers;
    bool m_skipKnownFrames;
    bool m_debugDumpers;
    bool m_useToolTips;
    bool m_listSourceFiles;

    QString m_scriptFile;

    bool m_pluginAllBreakpoints;
    bool m_pluginSelectedBreakpoints;
    bool m_pluginNoBreakpoints;
    QString m_pluginSelectedBreakpointsPattern;
#endif

QtcSettingsPool *theDebuggerSettings()
{
    static QtcSettingsPool *instance = 0;
    if (instance)
        return instance;

    instance = new QtcSettingsPool;

    QtcSettingsItem *item = 0;

    item = new QtcSettingsItem(instance);
    instance->insertItem(AdjustColumnWidths, item);
    item->setText(QObject::tr("Adjust column widths to contents"));

    item = new QtcSettingsItem(instance);
    instance->insertItem(AlwaysAdjustColumnWidths, item);
    item->setText(QObject::tr("Always adjust column widths to contents"));
    item->action()->setCheckable(true);

    item = new QtcSettingsItem(instance);
    instance->insertItem(WatchExpression, item);
    item->setTextPattern(QObject::tr("Watch expression \"%1\""));

    item = new QtcSettingsItem(instance);
    instance->insertItem(RemoveWatchExpression, item);
    item->setTextPattern(QObject::tr("Remove watch expression \"%1\""));

    item = new QtcSettingsItem(instance);
    instance->insertItem(SettingsDialog, item);
    item->setText(QObject::tr("Debugger properties..."));

    item = new QtcSettingsItem(instance);
    instance->insertItem(DebugDumpers, item);
    item->setText(QObject::tr("Debug custom dumpers"));
    item->action()->setCheckable(true);

    item = new QtcSettingsItem(instance);
    instance->insertItem(RecheckDumpers, item);
    item->setText(QObject::tr("Recheck custom dumper availability"));

    //
    // Breakpoints
    //
    item = new QtcSettingsItem(instance);
    instance->insertItem(SynchronizeBreakpoints, item);
    item->setText(QObject::tr("Syncronize breakpoints"));

    //
    item = new QtcSettingsItem(instance);
    instance->insertItem(AutoQuit, item);
    item->setText(QObject::tr("Automatically quit debugger"));
    item->action()->setCheckable(true);

    item = new QtcSettingsItem(instance);
    instance->insertItem(SkipKnownFrames, item);
    item->setText(QObject::tr("Skip known frames"));
    item->action()->setCheckable(true);

    item = new QtcSettingsItem(instance);
    instance->insertItem(UseToolTips, item);
    item->setText(QObject::tr("Use tooltips when debugging"));
    item->action()->setCheckable(true);

    item = new QtcSettingsItem(instance);
    instance->insertItem(ListSourceFiles, item);
    item->setText(QObject::tr("List source files"));
    item->action()->setCheckable(true);

    //
    // Settings
    //
    item = new QtcSettingsItem(instance);
    instance->insertItem(GdbLocation, item);
    item->setSettingsKey("DebugMode", "Location");

    item = new QtcSettingsItem(instance);
    instance->insertItem(GdbEnvironment, item);
    item->setSettingsKey("DebugMode", "Environment");

    item = new QtcSettingsItem(instance);
    instance->insertItem(GdbScriptFile, item);
    item->setSettingsKey("DebugMode", "ScriptFile");

    item = new QtcSettingsItem(instance);
    instance->insertItem(GdbAutoQuit, item);
    item->setSettingsKey("DebugMode", "AutoQuit");

    item = new QtcSettingsItem(instance);
    instance->insertItem(GdbAutoRun, item);
    item->setSettingsKey("DebugMode", "AutoRun");

    item = new QtcSettingsItem(instance);
    instance->insertItem(UseToolTips, item);
    item->setSettingsKey("DebugMode", "UseToolTips");

    item = new QtcSettingsItem(instance);
    instance->insertItem(UseDumpers, item);
    item->setSettingsKey("DebugMode", "UseCustomDumpers");
    item->setText(QObject::tr("Use custom dumpers"));
    item->action()->setCheckable(true);

    item = new QtcSettingsItem(instance);
    instance->insertItem(ListSourceFiles, item);
    item->setSettingsKey("DebugMode", "ListSourceFiles");

    item = new QtcSettingsItem(instance);
    instance->insertItem(SkipKnownFrames, item);
    item->setSettingsKey("DebugMode", "SkipKnownFrames");

    item = new QtcSettingsItem(instance);
    instance->insertItem(DebugDumpers, item);
    item->setSettingsKey("DebugMode", "DebugDumpers");

    item = new QtcSettingsItem(instance);
    instance->insertItem(AllPluginBreakpoints, item);
    item->setSettingsKey("DebugMode", "AllPluginBreakpoints");

    item = new QtcSettingsItem(instance);
    instance->insertItem(SelectedPluginBreakpoints, item);
    item->setSettingsKey("DebugMode", "SelectedPluginBreakpoints");

    item = new QtcSettingsItem(instance);
    instance->insertItem(NoPluginBreakpoints, item);
    item->setSettingsKey("DebugMode", "NoPluginBreakpoints");

    item = new QtcSettingsItem(instance);
    instance->insertItem(SelectedPluginBreakpointsPattern, item);
    item->setSettingsKey("DebugMode", "SelectedPluginBreakpointsPattern");

    return instance;
}

QtcSettingsItem *theDebuggerSetting(int code)
{
    return theDebuggerSettings()->item(code);
}

bool theDebuggerBoolSetting(int code)
{
    return theDebuggerSettings()->item(code)->value().toBool();
}

QString theDebuggerStringSetting(int code)
{
    return theDebuggerSettings()->item(code)->value().toString();
}

} // namespace Internal
} // namespace Debugger

<commit_msg>debugger: less debug output<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact:  Qt Software Information (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
**************************************************************************/

#include "debuggeractions.h"

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

#include <QtCore/QSettings>
#include <QtGui/QAction>
#include <QtGui/QAbstractButton>
#include <QtGui/QRadioButton>
#include <QtGui/QCheckBox>
#include <QtGui/QLineEdit>

namespace Debugger {
namespace Internal {

//////////////////////////////////////////////////////////////////////////
//
// QtcSettingsItem
//
//////////////////////////////////////////////////////////////////////////

QtcSettingsItem::QtcSettingsItem(QObject *parent)
  : QObject(parent)
{
    m_action = new QAction(this);
    connect(m_action, SIGNAL(triggered(bool)), this, SLOT(actionTriggered(bool)));
}

QVariant QtcSettingsItem::value() const
{
    return m_value;
}

void QtcSettingsItem::setValue(const QVariant &value, bool doemit)
{
    if (value != m_value) {
        m_value = value;
        if (m_action->isCheckable())
            m_action->setChecked(m_value.toBool());
        if (doemit) {
            emit valueChanged(m_value);
            emit boolValueChanged(m_value.toBool());
            emit stringValueChanged(m_value.toString());
        }
    }
}

QVariant QtcSettingsItem::defaultValue() const
{
    return m_defaultValue;
}

void QtcSettingsItem::setDefaultValue(const QVariant &value)
{
    m_defaultValue = value;
}

QString QtcSettingsItem::settingsKey() const
{
    return m_settingsKey;
}

void QtcSettingsItem::setSettingsKey(const QString &key)
{
    m_settingsKey = key;
}

void QtcSettingsItem::setSettingsKey(const QString &group, const QString &key)
{
    m_settingsKey = key;
    m_settingsGroup = group;
}

QString QtcSettingsItem::settingsGroup() const
{
    return m_settingsGroup;
}

void QtcSettingsItem::setSettingsGroup(const QString &group)
{
    m_settingsGroup = group;
}

QString QtcSettingsItem::text() const
{
    return m_action->text();
}

void QtcSettingsItem::setText(const QString &value)
{
    if (!value.isEmpty() && !m_textPattern.isEmpty())
        m_action->setText(m_textPattern.arg(value));
    else
        m_action->setText(value);
}

QString QtcSettingsItem::textPattern() const
{
    return m_textPattern;
}

void QtcSettingsItem::setTextPattern(const QString &value)
{
    m_textPattern = value;
}

void QtcSettingsItem::readSettings(QSettings *settings)
{
    if (m_settingsGroup.isEmpty() || m_settingsKey.isEmpty())
        return;
    settings->beginGroup(m_settingsGroup);
    setValue(settings->value(m_settingsKey, m_defaultValue), false);
    //qDebug() << "READING: " << m_settingsKey << " -> " << m_value;
    settings->endGroup();
}

void QtcSettingsItem::writeSettings(QSettings *settings)
{
    if (m_settingsGroup.isEmpty() || m_settingsKey.isEmpty())
        return;
    settings->beginGroup(m_settingsGroup);
    settings->setValue(m_settingsKey, m_value);
    //qDebug() << "WRITING: " << m_settingsKey << " -> " << m_value;
    settings->endGroup();
}

QAction *QtcSettingsItem::action() const
{
    return m_action;
}

void QtcSettingsItem::connectWidget(QWidget *widget, ApplyMode applyMode)
{
    using namespace Core::Utils;
    //qDebug() << "CONNECT WIDGET " << widget << " TO " << m_settingsKey;
    m_applyModes[widget] = applyMode;
    m_deferedValue = m_value;
    if (QAbstractButton *button = qobject_cast<QAbstractButton *>(widget)) {
        if (button->isCheckable()) {
            button->setChecked(m_value.toBool());
            connect(button, SIGNAL(clicked(bool)),
                this, SLOT(checkableButtonClicked(bool)));
        } else {
            connect(button, SIGNAL(clicked()),
                this, SLOT(uncheckableButtonClicked()));
        }
    } else if (QLineEdit *lineEdit = qobject_cast<QLineEdit *>(widget)) {
        lineEdit->setText(m_value.toString());
        //qDebug() << "SETTING TEXT" << lineEdit->text();
        connect(lineEdit, SIGNAL(editingFinished()),
            this, SLOT(lineEditEditingFinished()));
    } else if (PathChooser *pathChooser = qobject_cast<PathChooser *>(widget)) {
        pathChooser->setPath(m_value.toString());
        connect(pathChooser, SIGNAL(editingFinished()),
            this, SLOT(pathChooserEditingFinished()));
        connect(pathChooser, SIGNAL(browsingFinished()),
            this, SLOT(pathChooserEditingFinished()));
    } else {
        qDebug() << "CANNOT CONNECT WIDGET " << widget;
    }
}

void QtcSettingsItem::apply(QSettings *s)
{
    setValue(m_deferedValue);
    if (s)
        writeSettings(s);
}

void QtcSettingsItem::uncheckableButtonClicked()
{
    QAbstractButton *button = qobject_cast<QAbstractButton *>(sender());
    QTC_ASSERT(button, return);
    //qDebug() << "UNCHECKABLE BUTTON: " << sender();
    m_action->trigger();
}

void QtcSettingsItem::checkableButtonClicked(bool)
{
    QAbstractButton *button = qobject_cast<QAbstractButton *>(sender());
    QTC_ASSERT(button, return);
    //qDebug() << "CHECKABLE BUTTON: " << sender();
    if (m_applyModes[sender()] == DeferedApply)
        m_deferedValue = button->isChecked();
    else
        setValue(button->isChecked());
}

void QtcSettingsItem::lineEditEditingFinished()
{
    QLineEdit *lineEdit = qobject_cast<QLineEdit *>(sender());
    QTC_ASSERT(lineEdit, return);
    //qDebug() << "LINEEDIT: " << sender() << lineEdit->text();
    if (m_applyModes[sender()] == DeferedApply)
        m_deferedValue = lineEdit->text();
    else
        setValue(lineEdit->text());
}

void QtcSettingsItem::pathChooserEditingFinished()
{
    using namespace Core::Utils;
    PathChooser *pathChooser = qobject_cast<PathChooser *>(sender());
    QTC_ASSERT(pathChooser, return);
    //qDebug() << "PATHCHOOSER: " << sender() << pathChooser->path();
    if (m_applyModes[sender()] == DeferedApply)
        m_deferedValue = pathChooser->path();
    else
        setValue(pathChooser->path());
}

void QtcSettingsItem::actionTriggered(bool on)
{
    Q_UNUSED(on);
    if (QAction *action = qobject_cast<QAction *>(sender())) {
        if (action->isCheckable())
            setValue(action->isChecked());
    }
}

//////////////////////////////////////////////////////////////////////////
//
// QtcSettingsPool
//
//////////////////////////////////////////////////////////////////////////

QtcSettingsPool::QtcSettingsPool(QObject *parent)
    : QObject(parent)
{}

QtcSettingsPool::~QtcSettingsPool()
{
    qDeleteAll(m_items);
}

void QtcSettingsPool::insertItem(int code, QtcSettingsItem *item)
{
    m_items[code] = item;
}

void QtcSettingsPool::readSettings(QSettings *settings)
{
    foreach (QtcSettingsItem *item, m_items)
        item->readSettings(settings);
}

void QtcSettingsPool::writeSettings(QSettings *settings)
{
    foreach (QtcSettingsItem *item, m_items)
        item->writeSettings(settings);
}

QtcSettingsItem *QtcSettingsPool::item(int code)
{
    QTC_ASSERT(m_items.value(code, 0), return 0);
    return m_items.value(code, 0);
}

QString QtcSettingsPool::dump()
{
    QString out;
    QTextStream ts(&out);
    ts  << "Debugger settings: ";
    foreach (QtcSettingsItem *item, m_items)
        ts << "\n" << item->value().toString();
    return out;
}

//////////////////////////////////////////////////////////////////////////
//
// Debugger specific stuff
//
//////////////////////////////////////////////////////////////////////////

#if 0
    QString dump();

    QString m_gdbCmd;
    QString m_gdbEnv;
    bool m_autoRun;
    bool m_autoQuit;

    bool m_useDumpers;
    bool m_skipKnownFrames;
    bool m_debugDumpers;
    bool m_useToolTips;
    bool m_listSourceFiles;

    QString m_scriptFile;

    bool m_pluginAllBreakpoints;
    bool m_pluginSelectedBreakpoints;
    bool m_pluginNoBreakpoints;
    QString m_pluginSelectedBreakpointsPattern;
#endif

QtcSettingsPool *theDebuggerSettings()
{
    static QtcSettingsPool *instance = 0;
    if (instance)
        return instance;

    instance = new QtcSettingsPool;

    QtcSettingsItem *item = 0;

    item = new QtcSettingsItem(instance);
    instance->insertItem(AdjustColumnWidths, item);
    item->setText(QObject::tr("Adjust column widths to contents"));

    item = new QtcSettingsItem(instance);
    instance->insertItem(AlwaysAdjustColumnWidths, item);
    item->setText(QObject::tr("Always adjust column widths to contents"));
    item->action()->setCheckable(true);

    item = new QtcSettingsItem(instance);
    instance->insertItem(WatchExpression, item);
    item->setTextPattern(QObject::tr("Watch expression \"%1\""));

    item = new QtcSettingsItem(instance);
    instance->insertItem(RemoveWatchExpression, item);
    item->setTextPattern(QObject::tr("Remove watch expression \"%1\""));

    item = new QtcSettingsItem(instance);
    instance->insertItem(SettingsDialog, item);
    item->setText(QObject::tr("Debugger properties..."));

    item = new QtcSettingsItem(instance);
    instance->insertItem(DebugDumpers, item);
    item->setText(QObject::tr("Debug custom dumpers"));
    item->action()->setCheckable(true);

    item = new QtcSettingsItem(instance);
    instance->insertItem(RecheckDumpers, item);
    item->setText(QObject::tr("Recheck custom dumper availability"));

    //
    // Breakpoints
    //
    item = new QtcSettingsItem(instance);
    instance->insertItem(SynchronizeBreakpoints, item);
    item->setText(QObject::tr("Syncronize breakpoints"));

    //
    item = new QtcSettingsItem(instance);
    instance->insertItem(AutoQuit, item);
    item->setText(QObject::tr("Automatically quit debugger"));
    item->action()->setCheckable(true);

    item = new QtcSettingsItem(instance);
    instance->insertItem(SkipKnownFrames, item);
    item->setText(QObject::tr("Skip known frames"));
    item->action()->setCheckable(true);

    item = new QtcSettingsItem(instance);
    instance->insertItem(UseToolTips, item);
    item->setText(QObject::tr("Use tooltips when debugging"));
    item->action()->setCheckable(true);

    item = new QtcSettingsItem(instance);
    instance->insertItem(ListSourceFiles, item);
    item->setText(QObject::tr("List source files"));
    item->action()->setCheckable(true);

    //
    // Settings
    //
    item = new QtcSettingsItem(instance);
    instance->insertItem(GdbLocation, item);
    item->setSettingsKey("DebugMode", "Location");

    item = new QtcSettingsItem(instance);
    instance->insertItem(GdbEnvironment, item);
    item->setSettingsKey("DebugMode", "Environment");

    item = new QtcSettingsItem(instance);
    instance->insertItem(GdbScriptFile, item);
    item->setSettingsKey("DebugMode", "ScriptFile");

    item = new QtcSettingsItem(instance);
    instance->insertItem(GdbAutoQuit, item);
    item->setSettingsKey("DebugMode", "AutoQuit");

    item = new QtcSettingsItem(instance);
    instance->insertItem(GdbAutoRun, item);
    item->setSettingsKey("DebugMode", "AutoRun");

    item = new QtcSettingsItem(instance);
    instance->insertItem(UseToolTips, item);
    item->setSettingsKey("DebugMode", "UseToolTips");

    item = new QtcSettingsItem(instance);
    instance->insertItem(UseDumpers, item);
    item->setSettingsKey("DebugMode", "UseCustomDumpers");
    item->setText(QObject::tr("Use custom dumpers"));
    item->action()->setCheckable(true);

    item = new QtcSettingsItem(instance);
    instance->insertItem(ListSourceFiles, item);
    item->setSettingsKey("DebugMode", "ListSourceFiles");

    item = new QtcSettingsItem(instance);
    instance->insertItem(SkipKnownFrames, item);
    item->setSettingsKey("DebugMode", "SkipKnownFrames");

    item = new QtcSettingsItem(instance);
    instance->insertItem(DebugDumpers, item);
    item->setSettingsKey("DebugMode", "DebugDumpers");

    item = new QtcSettingsItem(instance);
    instance->insertItem(AllPluginBreakpoints, item);
    item->setSettingsKey("DebugMode", "AllPluginBreakpoints");

    item = new QtcSettingsItem(instance);
    instance->insertItem(SelectedPluginBreakpoints, item);
    item->setSettingsKey("DebugMode", "SelectedPluginBreakpoints");

    item = new QtcSettingsItem(instance);
    instance->insertItem(NoPluginBreakpoints, item);
    item->setSettingsKey("DebugMode", "NoPluginBreakpoints");

    item = new QtcSettingsItem(instance);
    instance->insertItem(SelectedPluginBreakpointsPattern, item);
    item->setSettingsKey("DebugMode", "SelectedPluginBreakpointsPattern");

    return instance;
}

QtcSettingsItem *theDebuggerSetting(int code)
{
    return theDebuggerSettings()->item(code);
}

bool theDebuggerBoolSetting(int code)
{
    return theDebuggerSettings()->item(code)->value().toBool();
}

QString theDebuggerStringSetting(int code)
{
    return theDebuggerSettings()->item(code)->value().toString();
}

} // namespace Internal
} // namespace Debugger

<|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)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "formeditorstack.h"
#include "designerxmleditor.h"
#include <QDesignerFormWindowInterface>
#include <texteditor/basetextdocument.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/icore.h>
#include "formwindoweditor.h"
#include "formeditorw.h"
#include "designerconstants.h"

#include <QtCore/QStringList>

namespace Designer {
namespace Internal {

FormEditorStack::FormEditorStack() : activeEditor(0)
{

}

FormEditorStack::~FormEditorStack()
{
    qDeleteAll(m_formEditors);
}

Designer::FormWindowEditor *FormEditorStack::createFormWindowEditor(DesignerXmlEditorEditable *xmlEditor)
{
    FormXmlData *data = new FormXmlData;
    data->formEditor = FormEditorW::instance()->createFormWindowEditor(this);
    data->formEditor->setFile(xmlEditor->file());
    data->xmlEditor = xmlEditor;
    data->widgetIndex = addWidget(data->formEditor->widget());
    m_formEditors.append(data);

    setFormEditorData(data->formEditor, xmlEditor->contents());

    TextEditor::BaseTextDocument *document = qobject_cast<TextEditor::BaseTextDocument*>(xmlEditor->file());
    connect(document, SIGNAL(reloaded()), SLOT(reloadDocument()));

    return data->formEditor;
}

bool FormEditorStack::removeFormWindowEditor(Core::IEditor *xmlEditor)
{
    for(int i = 0; i < m_formEditors.length(); ++i) {
        if (m_formEditors[i]->xmlEditor == xmlEditor) {
            disconnect(m_formEditors[i]->formEditor->formWindow(), SIGNAL(changed()), this, SLOT(formChanged()));
            removeWidget(m_formEditors[i]->formEditor->widget());
            delete m_formEditors[i]->formEditor;
            m_formEditors.removeAt(i);
            return true;
        }
    }
    return false;
}

bool FormEditorStack::setVisibleEditor(Core::IEditor *xmlEditor)
{
    for(int i = 0; i < m_formEditors.length(); ++i) {
        if (m_formEditors[i]->xmlEditor == xmlEditor) {
            setCurrentIndex(m_formEditors[i]->widgetIndex);
            activeEditor = m_formEditors[i];
            return true;
        }
    }
    return false;
}

Designer::FormWindowEditor *FormEditorStack::formWindowEditorForXmlEditor(Core::IEditor *xmlEditor)
{
    foreach(FormXmlData *data, m_formEditors) {
        if (data->xmlEditor == xmlEditor)
            return data->formEditor;
    }
    return 0;
}

void FormEditorStack::reloadDocument()
{
    if (activeEditor) {
        setFormEditorData(activeEditor->formEditor, activeEditor->xmlEditor->contents());
    }
}

void FormEditorStack::setFormEditorData(Designer::FormWindowEditor *formEditor, const QString &contents)
{
    disconnect(formEditor->formWindow(), SIGNAL(changed()), this, SLOT(formChanged()));
    formEditor->createNew(contents);
    connect(formEditor->formWindow(), SIGNAL(changed()), SLOT(formChanged()));
}

void FormEditorStack::formChanged()
{
    Core::ICore *core = Core::ICore::instance();

    if (core->editorManager()->currentEditor() && activeEditor
        && core->editorManager()->currentEditor() == activeEditor->xmlEditor)
    {
        TextEditor::BaseTextDocument *doc = qobject_cast<TextEditor::BaseTextDocument*>(activeEditor->xmlEditor->file());
        Q_ASSERT(doc);
        if (doc) {
            doc->document()->setPlainText(activeEditor->formEditor->contents());
        }
    }

}

} // Internal
} // Designer
<commit_msg>Design mode: Suppress warning about top level spacers.<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)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "formeditorstack.h"
#include "designerxmleditor.h"
#include <QDesignerFormWindowInterface>
#include <texteditor/basetextdocument.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/icore.h>
#include "formwindoweditor.h"
#include "formeditorw.h"
#include "designerconstants.h"
#include "qt_private/formwindowbase_p.h"

#include <QtCore/QStringList>

namespace Designer {
namespace Internal {

FormEditorStack::FormEditorStack() : activeEditor(0)
{

}

FormEditorStack::~FormEditorStack()
{
    qDeleteAll(m_formEditors);
}

Designer::FormWindowEditor *FormEditorStack::createFormWindowEditor(DesignerXmlEditorEditable *xmlEditor)
{
    FormXmlData *data = new FormXmlData;
    data->formEditor = FormEditorW::instance()->createFormWindowEditor(this);
    data->formEditor->setFile(xmlEditor->file());
    data->xmlEditor = xmlEditor;
    data->widgetIndex = addWidget(data->formEditor->widget());
    m_formEditors.append(data);

    setFormEditorData(data->formEditor, xmlEditor->contents());

    TextEditor::BaseTextDocument *document = qobject_cast<TextEditor::BaseTextDocument*>(xmlEditor->file());
    connect(document, SIGNAL(reloaded()), SLOT(reloadDocument()));

    return data->formEditor;
}

bool FormEditorStack::removeFormWindowEditor(Core::IEditor *xmlEditor)
{
    for(int i = 0; i < m_formEditors.length(); ++i) {
        if (m_formEditors[i]->xmlEditor == xmlEditor) {
            disconnect(m_formEditors[i]->formEditor->formWindow(), SIGNAL(changed()), this, SLOT(formChanged()));
            removeWidget(m_formEditors[i]->formEditor->widget());
            delete m_formEditors[i]->formEditor;
            m_formEditors.removeAt(i);
            return true;
        }
    }
    return false;
}

bool FormEditorStack::setVisibleEditor(Core::IEditor *xmlEditor)
{
    for(int i = 0; i < m_formEditors.length(); ++i) {
        if (m_formEditors[i]->xmlEditor == xmlEditor) {
            setCurrentIndex(m_formEditors[i]->widgetIndex);
            activeEditor = m_formEditors[i];
            return true;
        }
    }
    return false;
}

Designer::FormWindowEditor *FormEditorStack::formWindowEditorForXmlEditor(Core::IEditor *xmlEditor)
{
    foreach(FormXmlData *data, m_formEditors) {
        if (data->xmlEditor == xmlEditor)
            return data->formEditor;
    }
    return 0;
}

void FormEditorStack::reloadDocument()
{
    if (activeEditor) {
        setFormEditorData(activeEditor->formEditor, activeEditor->xmlEditor->contents());
    }
}

void FormEditorStack::setFormEditorData(Designer::FormWindowEditor *formEditor, const QString &contents)
{
    disconnect(formEditor->formWindow(), SIGNAL(changed()), this, SLOT(formChanged()));
    formEditor->createNew(contents);
    connect(formEditor->formWindow(), SIGNAL(changed()), SLOT(formChanged()));
}

void FormEditorStack::formChanged()
{
    Core::ICore *core = Core::ICore::instance();

    if (core->editorManager()->currentEditor() && activeEditor
        && core->editorManager()->currentEditor() == activeEditor->xmlEditor)
    {
        TextEditor::BaseTextDocument *doc = qobject_cast<TextEditor::BaseTextDocument*>(activeEditor->xmlEditor->file());
        Q_ASSERT(doc);
        if (doc) {
            // Save quietly (without spacer's warning).
            if (const qdesigner_internal::FormWindowBase *fwb = qobject_cast<const qdesigner_internal::FormWindowBase *>(activeEditor->formEditor->formWindow()))
                doc->document()->setPlainText(fwb->fileContents());
        }
    }
}

} // Internal
} // Designer
<|endoftext|>


<commit_before>#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
typedef vector< pair<int,pii> > vii;

// union find structure
vector<int> father,rank;//en c++11 se caga por el nombre rank
inline void initUF(int n)
{
  rank.resize(n);
  father.resize(n);
  for(int i = 0  ; i < n; ++i)
    father[i] = i;
}

int find(int x)
{
  if(x == father[x])
    return x;
  return find(father[x]);
}

inline int join(int x,int y) // path compression.
{
  int xroot = find(x), yroot = find(y);
  if(rank[x] > rank[y])
    father[y] = father[x];
  else
    {
      if(rank[y] > rank[x])
	father[x] = father[y];
      else
	{
	  father[y] = father[x];
	  ++rank[x];
	}
    }
}

// union find structure
//kruskal

inline long long Kruskal(vii Graph,int n) // vector< weight, pair<from,to> >
{
  sort(Graph.begin(),Graph.end());
  initUF(n);
  int u = 0;
  long long tweight = 0;
  for(int i = 0 ; i < Graph.size() ; ++i)
    {
      if(find(Graph[i].second.first) != find(Graph[i].second.second) )
	{
	  ++u;
	  tweight+=Graph[i].first;
	  if(u == n-1)
	    return tweight;
	  join(Graph[i].second.first,Graph[i].second.second);
	}
    }
  return -1;
}
//Kruskal

int main()
{
  int weight,from,to,n,e;
  vii grafo;
  cin >> n >> e;
  for(int i = 0 ; i < e ; ++i)
    {
      cin >> weight >> from >> to;
      grafo.push_back(make_pair(weight,make_pair(from,to)));
      grafo.push_back(make_pair(weight,make_pair(to,from)));
    }
  cout << Kruskal(grafo,n) << "\n";
  return 0;
}
<commit_msg>Delete Kruskal.cc<commit_after><|endoftext|>


<commit_before>/**
 * The Seeks proxy and plugin framework are part of the SEEKS project.
 * Copyright (C) 2009 - 2011 Emmanuel Benazera <ebenazer@seeks-project.info>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "se_parser_bing.h"
#include "miscutil.h"

#include <strings.h>
#include <iostream>

using sp::miscutil;

namespace seeks_plugins
{
  std::string se_parser_bing::_bing_stupid[2] =
  { "Document title", "Titre du document / Document title" };

  se_parser_bing::se_parser_bing(const std::string &url)
    :se_parser(url),_h1_sr_flag(false),_results_flag(false),_h3_flag(false),
     _link_flag(false),_p_flag(false),_cite_flag(false),_cached_flag(false)
  {
  }

  se_parser_bing::~se_parser_bing()
  {
  }

  void se_parser_bing::start_element(parser_context *pc,
                                     const xmlChar *name,
                                     const xmlChar **attributes)
  {
    const char *tag = (const char*)name;

    if (strcasecmp(tag,"h1") == 0)
      {
        _h1_sr_flag = true;
      }
    if (strcasecmp(tag,"div") == 0)
      {
        const char *a_class = se_parser::get_attribute((const char**)attributes,"class");

        if (a_class && strcasecmp(a_class,"sb_tlst") == 0)
          {
            if (pc->_snippets->empty())
              _results_flag = true;

            // assert previous snippet if any.
            if (pc->_current_snippet)
              {
                if (pc->_current_snippet->_title.empty()  // consider the parsing did fail on the snippet.
                    || pc->_current_snippet->_url.empty()
                    || pc->_current_snippet->_summary.empty()
                    || pc->_current_snippet->_cite.empty())
                  {
                    delete pc->_current_snippet;
                    pc->_current_snippet = NULL;
                    _count--;
                    pc->_snippets->pop_back();
                  }
              }

            // create new snippet.
            search_snippet *sp = new search_snippet(_count+1);
            _count++;
            sp->_engine = feeds("bing",_url);
            pc->_current_snippet = sp;
            pc->_snippets->push_back(pc->_current_snippet);

            _cached_flag = false; // in case previous snippet did not close the cached flag.
          }
      }
    else if (_results_flag && strcasecmp(tag,"h2") == 0)
      {
        _results_flag = false;
      }
    else if (_results_flag && _h1_sr_flag && strcasecmp(tag,"h3") == 0)
      {
        _h3_flag = true;
      }
    else if (_results_flag && _h1_sr_flag && _h3_flag && strcasecmp(tag,"a") == 0)
      {
        _link_flag = true;
        const char *a_link = se_parser::get_attribute((const char**)attributes,"href");

        if (a_link)
          _link = std::string(a_link);
      }
    else if (_results_flag && _h1_sr_flag && strcasecmp(tag,"p") == 0)
      {
        _p_flag = true;
      }
    else if (_results_flag && _h1_sr_flag && strcasecmp(tag,"cite") == 0)
      {
        _cite_flag = true;
      }
    else if (_results_flag && _h1_sr_flag && _cached_flag && strcasecmp(tag,"a") == 0) // may not be very robust...
      {
        _cached_flag = false;
        const char *a_link = se_parser::get_attribute((const char**)attributes,"href");
        if (a_link)
          pc->_current_snippet->_cached = std::string(a_link);
      }
  }

  void se_parser_bing::characters(parser_context *pc,
                                  const xmlChar *chars,
                                  int length)
  {
    handle_characters(pc, chars, length);
  }

  void se_parser_bing::cdata(parser_context *pc,
                             const xmlChar *chars,
                             int length)
  {
    handle_characters(pc, chars, length);
  }

  void se_parser_bing::handle_characters(parser_context *pc,
                                         const xmlChar *chars,
                                         int length)
  {
    if (_p_flag)
      {
        std::string a_chars = std::string((char*)chars);
        miscutil::replace_in_string(a_chars,"\n"," ");
        miscutil::replace_in_string(a_chars,"\r"," ");
        miscutil::replace_in_string(a_chars,"-"," ");
        miscutil::replace_in_string(a_chars,se_parser_bing::_bing_stupid[1],"");
        miscutil::replace_in_string(a_chars,se_parser_bing::_bing_stupid[0],"");
        _summary += a_chars;
      }
    else if (_cite_flag)
      {
        std::string a_chars = std::string((char*)chars);
        miscutil::replace_in_string(a_chars,"\n"," ");
        miscutil::replace_in_string(a_chars,"\r"," ");
        //miscutil::replace_in_string(a_chars,"-"," ");
        _cite += a_chars;
      }
    else if (_h3_flag)
      {
        std::string a_chars = std::string((char*)chars);
        miscutil::replace_in_string(a_chars,"\n"," ");
        miscutil::replace_in_string(a_chars,"\r"," ");
        _h3 += a_chars;
      }

  }

  void se_parser_bing::end_element(parser_context *pc,
                                   const xmlChar *name)
  {
    const char *tag = (const char*) name;

    if (!_results_flag)
      return;

    if (_h1_sr_flag && _h3_flag && strcasecmp(tag,"a") == 0)
      {
        _link_flag = false;
        pc->_current_snippet->set_url(_link);
        _link = "";
      }
    else if (_p_flag && strcasecmp(tag,"p") == 0)
      {
        _p_flag = false;
        pc->_current_snippet->set_summary(_summary);
        _summary = "";
      }
    else if (_cite_flag && strcasecmp(tag,"cite") == 0)
      {
        _cite_flag = false;
        pc->_current_snippet->set_cite(_cite);
        _cite = "";
        _cached_flag = true; // getting ready for the Cached link, if any.
      }
    else if (_h3_flag && strcasecmp(tag,"h3") == 0)
      {
        _h3_flag = false;
        pc->_current_snippet->set_title(_h3);
        _h3 = "";
      }

  }

} /* end of namespace. */
<commit_msg>Bing parser fix: was failing to report all results on some queries, due to some changes in the Bing UI as it seems<commit_after>/**
 * The Seeks proxy and plugin framework are part of the SEEKS project.
 * Copyright (C) 2009 - 2011 Emmanuel Benazera <ebenazer@seeks-project.info>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "se_parser_bing.h"
#include "miscutil.h"

#include <strings.h>
#include <iostream>

using sp::miscutil;

namespace seeks_plugins
{
  std::string se_parser_bing::_bing_stupid[2] =
  { "Document title", "Titre du document / Document title" };

  se_parser_bing::se_parser_bing(const std::string &url)
    :se_parser(url),_h1_sr_flag(false),_results_flag(false),_h3_flag(false),
     _link_flag(false),_p_flag(false),_cite_flag(false),_cached_flag(false)
  {
  }

  se_parser_bing::~se_parser_bing()
  {
  }

  void se_parser_bing::start_element(parser_context *pc,
                                     const xmlChar *name,
                                     const xmlChar **attributes)
  {
    const char *tag = (const char*)name;

    if (strcasecmp(tag,"h1") == 0)
      {
        _h1_sr_flag = true;
      }
    if (strcasecmp(tag,"div") == 0)
      {
        const char *a_class = se_parser::get_attribute((const char**)attributes,"class");

        if (a_class && strcasecmp(a_class,"sb_tlst") == 0)
          {
            if (pc->_snippets->empty())
              _results_flag = true;

            // create new snippet.
            search_snippet *sp = new search_snippet(_count+1);
            _count++;
            sp->_engine = feeds("bing",_url);
            pc->_current_snippet = sp;

            _cached_flag = false; // in case previous snippet did not close the cached flag.
          }
        else if (_results_flag && a_class && (strcasecmp(a_class,"sa_cc")==0
                                              || strcasecmp(a_class,"sb_pag")==0))
          {
            // assert previous snippet if any.
            if (pc->_current_snippet)
              {
                if (pc->_current_snippet->_title.empty()  // consider the parsing did fail on the snippet.
                    || pc->_current_snippet->_url.empty()
                    || pc->_current_snippet->_summary.empty()
                    || pc->_current_snippet->_cite.empty())
                  {
                    delete pc->_current_snippet;
                    pc->_current_snippet = NULL;
                    _count--;
                  }
                else pc->_snippets->push_back(pc->_current_snippet);
              }
          }
      }
    /*else if (_results_flag && strcasecmp(tag,"h2") == 0)
      {
        _results_flag = false;
    }*/
    else if (_results_flag && _h1_sr_flag && strcasecmp(tag,"h3") == 0)
      {
        _h3_flag = true;
      }
    else if (_results_flag && _h1_sr_flag && _h3_flag && strcasecmp(tag,"a") == 0)
      {
        _link_flag = true;
        const char *a_link = se_parser::get_attribute((const char**)attributes,"href");

        if (a_link)
          _link = std::string(a_link);
      }
    else if (_results_flag && _h1_sr_flag && strcasecmp(tag,"p") == 0)
      {
        _p_flag = true;
      }
    else if (_results_flag && _h1_sr_flag && strcasecmp(tag,"cite") == 0)
      {
        _cite_flag = true;
      }
    else if (_results_flag && _h1_sr_flag && _cached_flag && strcasecmp(tag,"a") == 0) // may not be very robust...
      {
        _cached_flag = false;
        const char *a_link = se_parser::get_attribute((const char**)attributes,"href");
        if (a_link)
          pc->_current_snippet->_cached = std::string(a_link);
      }
  }

  void se_parser_bing::characters(parser_context *pc,
                                  const xmlChar *chars,
                                  int length)
  {
    handle_characters(pc, chars, length);
  }

  void se_parser_bing::cdata(parser_context *pc,
                             const xmlChar *chars,
                             int length)
  {
    handle_characters(pc, chars, length);
  }

  void se_parser_bing::handle_characters(parser_context *pc,
                                         const xmlChar *chars,
                                         int length)
  {
    if (_p_flag)
      {
        std::string a_chars = std::string((char*)chars);
        miscutil::replace_in_string(a_chars,"\n"," ");
        miscutil::replace_in_string(a_chars,"\r"," ");
        miscutil::replace_in_string(a_chars,"-"," ");
        miscutil::replace_in_string(a_chars,se_parser_bing::_bing_stupid[1],"");
        miscutil::replace_in_string(a_chars,se_parser_bing::_bing_stupid[0],"");
        _summary += a_chars;
      }
    else if (_cite_flag)
      {
        std::string a_chars = std::string((char*)chars);
        miscutil::replace_in_string(a_chars,"\n"," ");
        miscutil::replace_in_string(a_chars,"\r"," ");
        //miscutil::replace_in_string(a_chars,"-"," ");
        _cite += a_chars;
      }
    else if (_h3_flag)
      {
        std::string a_chars = std::string((char*)chars);
        miscutil::replace_in_string(a_chars,"\n"," ");
        miscutil::replace_in_string(a_chars,"\r"," ");
        _h3 += a_chars;
      }

  }

  void se_parser_bing::end_element(parser_context *pc,
                                   const xmlChar *name)
  {
    const char *tag = (const char*) name;

    if (!_results_flag)
      return;

    if (_h1_sr_flag && _h3_flag && strcasecmp(tag,"a") == 0)
      {
        _link_flag = false;
        pc->_current_snippet->set_url(_link);
        _link = "";
      }
    else if (_p_flag && strcasecmp(tag,"p") == 0)
      {
        _p_flag = false;
        pc->_current_snippet->set_summary(_summary);
        _summary = "";
      }
    else if (_cite_flag && strcasecmp(tag,"cite") == 0)
      {
        _cite_flag = false;
        pc->_current_snippet->set_cite(_cite);
        _cite = "";
        _cached_flag = true; // getting ready for the Cached link, if any.
      }
    else if (_h3_flag && strcasecmp(tag,"h3") == 0)
      {
        _h3_flag = false;
        pc->_current_snippet->set_title(_h3);
        _h3 = "";
      }

  }

} /* end of namespace. */
<|endoftext|>


<commit_before>#include "messages/layouts/messagelayout.hpp"
#include "singletons/emotemanager.hpp"
#include "singletons/settingsmanager.hpp"

#include <QApplication>
#include <QDebug>
#include <QPainter>
#include <QThread>
#include <QtGlobal>

#define MARGIN_LEFT (int)(8 * this->scale)
#define MARGIN_RIGHT (int)(8 * this->scale)
#define MARGIN_TOP (int)(4 * this->scale)
#define MARGIN_BOTTOM (int)(4 * this->scale)
#define COMPACT_EMOTES_OFFSET 6

namespace chatterino {
namespace messages {
namespace layouts {

MessageLayout::MessageLayout(MessagePtr _message)
    : message(_message)
    , buffer(nullptr)
{
    if (_message->flags & Message::Collapsed) {
        this->flags &= MessageLayout::Collapsed;
    }
}

Message *MessageLayout::getMessage()
{
    return this->message.get();
}

// Height
int MessageLayout::getHeight() const
{
    return container.getHeight();
}

// Layout
// return true if redraw is required
bool MessageLayout::layout(int width, float scale, MessageElement::Flags flags)
{
    auto &emoteManager = singletons::EmoteManager::getInstance();

    bool layoutRequired = false;

    // check if width changed
    bool widthChanged = width != this->currentLayoutWidth;
    layoutRequired |= widthChanged;
    this->currentLayoutWidth = width;

    // check if emotes changed
    bool imagesChanged = this->emoteGeneration != emoteManager.getGeneration();
    layoutRequired |= imagesChanged;
    this->emoteGeneration = emoteManager.getGeneration();

    // check if text changed
    bool textChanged =
        this->fontGeneration != singletons::FontManager::getInstance().getGeneration();
    layoutRequired |= textChanged;
    this->fontGeneration = singletons::FontManager::getInstance().getGeneration();

    // check if work mask changed
    bool wordMaskChanged = this->currentWordFlags !=
                           flags;  // singletons::SettingManager::getInstance().getWordTypeMask();
    layoutRequired |= wordMaskChanged;
    this->currentWordFlags = flags;  // singletons::SettingManager::getInstance().getWordTypeMask();

    // check if timestamp format changed
    bool timestampFormatChanged =
        this->timestampFormat != singletons::SettingManager::getInstance().timestampFormat;

    layoutRequired |= timestampFormatChanged;

    // check if dpi changed
    bool scaleChanged = this->scale != scale;
    layoutRequired |= scaleChanged;
    this->scale = scale;
    imagesChanged |= scaleChanged;
    textChanged |= scaleChanged;

    // update word sizes if needed
    if (imagesChanged) {
        //        this->container.updateImages();
        this->flags &= MessageLayout::RequiresBufferUpdate;
    }
    if (textChanged) {
        //        this->container.updateText();
        this->flags &= MessageLayout::RequiresBufferUpdate;
    }
    if (widthChanged || wordMaskChanged) {
        this->deleteBuffer();
    }

    // return if no layout is required
    if (!layoutRequired) {
        return false;
    }

    this->actuallyLayout(width, flags);
    this->invalidateBuffer();

    return true;
}

void MessageLayout::actuallyLayout(int width, MessageElement::Flags flags)
{
    this->container.begin(width, this->scale, this->message->flags.value);

    for (const std::unique_ptr<MessageElement> &element : this->message->getElements()) {
        element->addToContainer(this->container, flags);
    }

    if (this->height != this->container.getHeight()) {
        this->deleteBuffer();
    }

    this->container.finish();
    this->height = this->container.getHeight();
}

// Painting
void MessageLayout::paint(QPainter &painter, int y, int messageIndex, Selection &selection,
                          bool isLastReadMessage, bool isWindowFocused)
{
    QPixmap *pixmap = this->buffer.get();
    singletons::ThemeManager &themeManager = singletons::ThemeManager::getInstance();

    // create new buffer if required
    if (!pixmap) {
#ifdef Q_OS_MACOS
        pixmap =
            new QPixmap((int)(this->container.width * painter.device()->devicePixelRatioF()),
                        (int)(this->container.getHeight() * painter.device()->devicePixelRatioF()));
        pixmap->setDevicePixelRatio(painter.device()->devicePixelRatioF());
#else
        pixmap = new QPixmap(this->container.getWidth(), std::max(16, this->container.getHeight()));
#endif

        this->buffer = std::shared_ptr<QPixmap>(pixmap);
        this->bufferValid = false;
    }

    if (!this->bufferValid || !selection.isEmpty()) {
        this->updateBuffer(pixmap, messageIndex, selection);
    }

    // draw on buffer
    painter.drawPixmap(0, y, *pixmap);
    //    painter.drawPixmap(0, y, this->container.width, this->container.getHeight(), *pixmap);

    // draw disabled
    if (this->message->flags & Message::Disabled) {
        painter.fillRect(0, y, pixmap->width(), pixmap->height(), themeManager.messages.disabled);
    }

    // draw gif emotes
    this->container.paintAnimatedElements(painter, y);

    // draw last read message line
    if (isLastReadMessage) {
        QColor color = isWindowFocused ? themeManager.tabs.selected.backgrounds.regular.color()
                                       : themeManager.tabs.selected.backgrounds.unfocused.color();

        QBrush brush = QBrush(color, Qt::VerPattern);

        painter.fillRect(0, y + this->container.getHeight() - 1, this->container.getWidth(), 1,
                         brush);
    }

    this->bufferValid = true;
}

void MessageLayout::updateBuffer(QPixmap *buffer, int messageIndex, Selection &selection)
{
    singletons::ThemeManager &themeManager = singletons::ThemeManager::getInstance();

    QPainter painter(buffer);

    painter.setRenderHint(QPainter::SmoothPixmapTransform);

    // draw background
    painter.fillRect(buffer->rect(), this->message->flags & Message::Highlighted
                                         ? themeManager.messages.backgrounds.highlighted
                                         : themeManager.messages.backgrounds.regular);

    // draw selection
    if (!selection.isEmpty()) {
        this->container.paintSelection(painter, messageIndex, selection);
    }

    // draw message
    this->container.paintElements(painter);

#ifdef OHHEYITSFOURTF
    // debug
    painter.setPen(QColor(255, 0, 0));
    painter.drawRect(buffer->rect().x(), buffer->rect().y(), buffer->rect().width() - 1,
                     buffer->rect().height() - 1);

    QTextOption option;
    option.setAlignment(Qt::AlignRight | Qt::AlignTop);

    painter.drawText(QRectF(1, 1, this->container.width - 3, 1000),
                     QString::number(++this->bufferUpdatedCount), option);
#endif
}

void MessageLayout::invalidateBuffer()
{
    this->bufferValid = false;
}

void MessageLayout::deleteBuffer()
{
    this->buffer = nullptr;
}

// Elements
//    assert(QThread::currentThread() == QApplication::instance()->thread());

// returns nullptr if none was found

// fourtf: this should return a MessageLayoutItem
const MessageLayoutElement *MessageLayout::getElementAt(QPoint point)
{
    // go through all words and return the first one that contains the point.
    return this->container.getElementAt(point);
}

int MessageLayout::getLastCharacterIndex() const
{
    return this->container.getLastCharacterIndex();
}

int MessageLayout::getSelectionIndex(QPoint position)
{
    return this->container.getSelectionIndex(position);
}

void MessageLayout::addSelectionText(QString &str, int from, int to)
{
    this->container.addSelectionText(str, from, to);
}
}  // namespace layouts
}  // namespace messages
}  // namespace chatterino
<commit_msg>fixed compiling on macos<commit_after>#include "messages/layouts/messagelayout.hpp"
#include "singletons/emotemanager.hpp"
#include "singletons/settingsmanager.hpp"

#include <QApplication>
#include <QDebug>
#include <QPainter>
#include <QThread>
#include <QtGlobal>

#define MARGIN_LEFT (int)(8 * this->scale)
#define MARGIN_RIGHT (int)(8 * this->scale)
#define MARGIN_TOP (int)(4 * this->scale)
#define MARGIN_BOTTOM (int)(4 * this->scale)
#define COMPACT_EMOTES_OFFSET 6

namespace chatterino {
namespace messages {
namespace layouts {

MessageLayout::MessageLayout(MessagePtr _message)
    : message(_message)
    , buffer(nullptr)
{
    if (_message->flags & Message::Collapsed) {
        this->flags &= MessageLayout::Collapsed;
    }
}

Message *MessageLayout::getMessage()
{
    return this->message.get();
}

// Height
int MessageLayout::getHeight() const
{
    return container.getHeight();
}

// Layout
// return true if redraw is required
bool MessageLayout::layout(int width, float scale, MessageElement::Flags flags)
{
    auto &emoteManager = singletons::EmoteManager::getInstance();

    bool layoutRequired = false;

    // check if width changed
    bool widthChanged = width != this->currentLayoutWidth;
    layoutRequired |= widthChanged;
    this->currentLayoutWidth = width;

    // check if emotes changed
    bool imagesChanged = this->emoteGeneration != emoteManager.getGeneration();
    layoutRequired |= imagesChanged;
    this->emoteGeneration = emoteManager.getGeneration();

    // check if text changed
    bool textChanged =
        this->fontGeneration != singletons::FontManager::getInstance().getGeneration();
    layoutRequired |= textChanged;
    this->fontGeneration = singletons::FontManager::getInstance().getGeneration();

    // check if work mask changed
    bool wordMaskChanged = this->currentWordFlags !=
                           flags;  // singletons::SettingManager::getInstance().getWordTypeMask();
    layoutRequired |= wordMaskChanged;
    this->currentWordFlags = flags;  // singletons::SettingManager::getInstance().getWordTypeMask();

    // check if timestamp format changed
    bool timestampFormatChanged =
        this->timestampFormat != singletons::SettingManager::getInstance().timestampFormat;

    layoutRequired |= timestampFormatChanged;

    // check if dpi changed
    bool scaleChanged = this->scale != scale;
    layoutRequired |= scaleChanged;
    this->scale = scale;
    imagesChanged |= scaleChanged;
    textChanged |= scaleChanged;

    // update word sizes if needed
    if (imagesChanged) {
        //        this->container.updateImages();
        this->flags &= MessageLayout::RequiresBufferUpdate;
    }
    if (textChanged) {
        //        this->container.updateText();
        this->flags &= MessageLayout::RequiresBufferUpdate;
    }
    if (widthChanged || wordMaskChanged) {
        this->deleteBuffer();
    }

    // return if no layout is required
    if (!layoutRequired) {
        return false;
    }

    this->actuallyLayout(width, flags);
    this->invalidateBuffer();

    return true;
}

void MessageLayout::actuallyLayout(int width, MessageElement::Flags flags)
{
    this->container.begin(width, this->scale, this->message->flags.value);

    for (const std::unique_ptr<MessageElement> &element : this->message->getElements()) {
        element->addToContainer(this->container, flags);
    }

    if (this->height != this->container.getHeight()) {
        this->deleteBuffer();
    }

    this->container.finish();
    this->height = this->container.getHeight();
}

// Painting
void MessageLayout::paint(QPainter &painter, int y, int messageIndex, Selection &selection,
                          bool isLastReadMessage, bool isWindowFocused)
{
    QPixmap *pixmap = this->buffer.get();
    singletons::ThemeManager &themeManager = singletons::ThemeManager::getInstance();

    // create new buffer if required
    if (!pixmap) {
#ifdef Q_OS_MACOS
        pixmap =
            new QPixmap((int)(this->container.getWidth() * painter.device()->devicePixelRatioF()),
                        (int)(this->container.getHeight() * painter.device()->devicePixelRatioF()));
        pixmap->setDevicePixelRatio(painter.device()->devicePixelRatioF());
#else
        pixmap = new QPixmap(this->container.getWidth(), std::max(16, this->container.getHeight()));
#endif

        this->buffer = std::shared_ptr<QPixmap>(pixmap);
        this->bufferValid = false;
    }

    if (!this->bufferValid || !selection.isEmpty()) {
        this->updateBuffer(pixmap, messageIndex, selection);
    }

    // draw on buffer
    painter.drawPixmap(0, y, *pixmap);
    //    painter.drawPixmap(0, y, this->container.width, this->container.getHeight(), *pixmap);

    // draw disabled
    if (this->message->flags & Message::Disabled) {
        painter.fillRect(0, y, pixmap->width(), pixmap->height(), themeManager.messages.disabled);
    }

    // draw gif emotes
    this->container.paintAnimatedElements(painter, y);

    // draw last read message line
    if (isLastReadMessage) {
        QColor color = isWindowFocused ? themeManager.tabs.selected.backgrounds.regular.color()
                                       : themeManager.tabs.selected.backgrounds.unfocused.color();

        QBrush brush = QBrush(color, Qt::VerPattern);

        painter.fillRect(0, y + this->container.getHeight() - 1, this->container.getWidth(), 1,
                         brush);
    }

    this->bufferValid = true;
}

void MessageLayout::updateBuffer(QPixmap *buffer, int messageIndex, Selection &selection)
{
    singletons::ThemeManager &themeManager = singletons::ThemeManager::getInstance();

    QPainter painter(buffer);

    painter.setRenderHint(QPainter::SmoothPixmapTransform);

    // draw background
    painter.fillRect(buffer->rect(), this->message->flags & Message::Highlighted
                                         ? themeManager.messages.backgrounds.highlighted
                                         : themeManager.messages.backgrounds.regular);

    // draw selection
    if (!selection.isEmpty()) {
        this->container.paintSelection(painter, messageIndex, selection);
    }

    // draw message
    this->container.paintElements(painter);

#ifdef OHHEYITSFOURTF
    // debug
    painter.setPen(QColor(255, 0, 0));
    painter.drawRect(buffer->rect().x(), buffer->rect().y(), buffer->rect().width() - 1,
                     buffer->rect().height() - 1);

    QTextOption option;
    option.setAlignment(Qt::AlignRight | Qt::AlignTop);

    painter.drawText(QRectF(1, 1, this->container.width - 3, 1000),
                     QString::number(++this->bufferUpdatedCount), option);
#endif
}

void MessageLayout::invalidateBuffer()
{
    this->bufferValid = false;
}

void MessageLayout::deleteBuffer()
{
    this->buffer = nullptr;
}

// Elements
//    assert(QThread::currentThread() == QApplication::instance()->thread());

// returns nullptr if none was found

// fourtf: this should return a MessageLayoutItem
const MessageLayoutElement *MessageLayout::getElementAt(QPoint point)
{
    // go through all words and return the first one that contains the point.
    return this->container.getElementAt(point);
}

int MessageLayout::getLastCharacterIndex() const
{
    return this->container.getLastCharacterIndex();
}

int MessageLayout::getSelectionIndex(QPoint position)
{
    return this->container.getSelectionIndex(position);
}

void MessageLayout::addSelectionText(QString &str, int from, int to)
{
    this->container.addSelectionText(str, from, to);
}
}  // namespace layouts
}  // namespace messages
}  // namespace chatterino
<|endoftext|>