Browse Source

Better line length stuff...

Douglas William Thrift 14 years ago
parent
commit
0777854f03
1 changed files with 133 additions and 30 deletions
  1. 133 30
      dtpstree.cpp

+ 133 - 30
dtpstree.cpp

@@ -19,7 +19,9 @@
  *  limitations under the License.
  */
 
+#include <cerrno>
 #include <climits>
+#include <cstdarg>
 #include <cstdio>
 #include <cstdlib>
 #include <cstring>
@@ -38,7 +40,6 @@
 
 #include <curses.h>
 #include <err.h>
-#include <errno.h>
 #include <fcntl.h>
 #include <getopt.h>
 #include <kvm.h>
@@ -70,7 +71,7 @@ enum Flags
 	ShowKernel	= 0x0020,
 	Long		= 0x0040,
 	NumericSort	= 0x0080,
-	ShowPids	= 0x0104,
+	ShowPids	= 0x0100,
 	ShowTitles	= 0x0200,
 	UidChanges	= 0x0400,
 	Unicode		= 0x0800,
@@ -79,25 +80,38 @@ enum Flags
 	User		= 0x4000
 };
 
+enum Escape { None, BoxDrawing, Bright };
+
+struct Segment
+{
+	size_t width_;
+	Escape escape_;
+	char *string_;
+
+	inline Segment(size_t width, Escape escape, char *string) : width_(width), escape_(escape), string_(string) {}
+};
+
 struct Branch
 {
 	std::string indentation_;
 	bool done_;
 
-	Branch(size_t indentation) : indentation_(indentation, ' '), done_(false) {}
+	inline Branch(size_t indentation) : indentation_(indentation, ' '), done_(false) {}
 };
 
 class Tree
 {
-	const int &flags_;
+	const uint16_t &flags_;
 	bool vt100_;
 	wchar_t horizontal_, vertical_, upAndRight_, verticalAndRight_, downAndHorizontal_;
-	int width_;
+	size_t maxWidth_, width_;
+	bool max_, suppress_;
+	std::vector<Segment> segments_;
 	std::vector<Branch> branches_;
 	bool first_, last_;
 
 public:
-	Tree(const int &flags) : flags_(flags), vt100_(false)
+	Tree(const uint16_t &flags) : flags_(flags), vt100_(false), maxWidth_(0), width_(0), max_(false), suppress_(false)
 	{
 		bool tty(isatty(1));
 
@@ -124,7 +138,7 @@ public:
 
 			char *test;
 
-			if (asprintf(&test, "%C%C%C%C%C", horizontal_, vertical_, upAndRight_, verticalAndRight_, downAndHorizontal_) == -1)
+			if (asprintf(&test, "%lc%lc%lc%lc%lc", horizontal_, vertical_, upAndRight_, verticalAndRight_, downAndHorizontal_) == -1)
 				goto vt100;
 
 			std::free(test);
@@ -150,26 +164,28 @@ public:
 
 			if (setupterm(NULL, 1, &code) == OK)
 			{
-				width_ = tigetnum("cols");
+				maxWidth_ = tigetnum("cols");
 
-				if (!tigetflag("xenl"))
-					--width_;
+				if (tigetflag("am") && !tigetflag("xenl"))
+					suppress_ = true;
 			}
 			else
-				width_ = 79;
+				maxWidth_ = 80;
 		}
 	}
 
 	void print(const std::string &string, bool highlight)
 	{
-		if (vt100_)
-			std::printf("\033(0\017");
+		Escape escape(vt100_ ? BoxDrawing : None);
 
 		if (!first_ || flags_ & Arguments)
 		{
 			size_t last(branches_.size() - 1);
 
 			_foreach (std::vector<Branch>, branch, branches_)
+			{
+				size_t width(branch->indentation_.size() + 2);
+
 				if (_index == last)
 				{
 					wchar_t line;
@@ -182,10 +198,11 @@ public:
 					else
 						line = verticalAndRight_;
 
-					std::printf("%s%C%C", branch->indentation_.c_str(), line, horizontal_);
+					print(width, escape, "%s%lc%lc", branch->indentation_.c_str(), line, horizontal_);
 				}
 				else
-					std::printf("%s%C ", branch->indentation_.c_str(), branch->done_ ? ' ' : vertical_);
+					print(width, escape, "%s%lc ", branch->indentation_.c_str(), branch->done_ ? ' ' : vertical_);
+			}
 		}
 		else if (branches_.size())
 		{
@@ -199,20 +216,17 @@ public:
 			else
 				line = downAndHorizontal_;
 
-			std::printf("%C%C%C", horizontal_, line, horizontal_);
+			print(3, escape, "%lc%lc%lc", horizontal_, line, horizontal_);
 		}
 
-		if (vt100_)
-			std::printf("\033(B\017");
-
-		std::printf("%s%s%s", highlight ? "\033[1m" : "", string.c_str(), highlight ? "\033[22m" : "");
+		print(string.size(), highlight ? Bright : None, "%s", string.c_str());
 
 		branches_.push_back(Branch(!(flags_ & Arguments) ? string.size() + 1 : 2));
 	}
 
-	inline void printArg(const std::string &string) const
+	inline void printArg(const std::string &string)
 	{
-		std::printf(" %s", string.c_str());
+		//std::printf(" %s", string.c_str());
 	}
 
 	inline void pop(bool children)
@@ -220,21 +234,109 @@ public:
 		branches_.pop_back();
 
 		if (!(flags_ & Arguments) && !children)
+			done();
+	}
+
+	inline void done()
+	{
+		_foreach (std::vector<Segment>, segment, segments_)
+		{
+			const char *begin, *end;
+
+			switch (segment->escape_)
+			{
+			case BoxDrawing:
+				begin = "\033(0\017";
+				end = "\033(B\017";
+				break;
+			case Bright:
+				begin = "\033[1m";
+				end = "\033[22m";
+				break;
+			default:
+				begin = end = ""; break;
+			}
+
+			std::printf("%s%s%s", begin, segment->string_, end);
+			std::free(segment->string_);
+		}
+
+		segments_.clear();
+
+		if (suppress_ && width_ == maxWidth_)
+			std::fflush(stdout);
+		else
 			std::printf("\n");
+
+		width_ = 0;
+		max_ = false;
 	}
 
-	Tree &operator()(bool first, bool last)
+	inline Tree &operator()(bool first, bool last)
 	{
 		first_ = first;
 		last_ = last;
 
 		return *this;
 	}
+
+private:
+	void print(size_t width, Escape escape, const char * format, ...)
+	{
+		if (max_)
+			return;
+
+		std::va_list args;
+
+		va_start(args, format);
+
+		char *string;
+
+		vasprintf(&string, format, args);
+		va_end(args);
+
+		width_ += width;
+
+		if (maxWidth_ && !(flags_ & Long))
+			if (width_ > maxWidth_)
+			{
+				width -= (width_ - maxWidth_);
+				width_ = maxWidth_;
+				max_ = true;
+
+				bool previous = !width;
+
+				if (previous)
+				{
+					std::free(string);
+
+					const Segment &segment(segments_.back());
+
+					width = segment.width_;
+					string = segment.string_;
+				}
+
+				std::wstring wide(width - 1, '\0');
+
+				std::mbstowcs(const_cast<wchar_t *>(wide.data()), string, wide.size());
+				std::free(string);
+				asprintf(&string, "%ls+", wide.c_str());
+
+				if (previous)
+				{
+					segments_.back().string_ = string;
+
+					return;
+				}
+			}
+
+		segments_.push_back(Segment(width, escape, string));
+	}
 };
 
 class Proc
 {
-	const int &flags_;
+	const uint16_t &flags_;
 	kvm_t *kd_;
 	kinfo_proc *proc_;
 	mutable std::string name_;
@@ -244,7 +346,7 @@ class Proc
 	bool highlight_, root_;
 
 public:
-	inline Proc(const int &flags, kvm_t *kd, kinfo_proc *proc) : flags_(flags), kd_(kd), proc_(proc), highlight_(false), root_(false) {}
+	inline Proc(const uint16_t &flags, kvm_t *kd, kinfo_proc *proc) : flags_(flags), kd_(kd), proc_(proc), parent_(NULL), highlight_(false), root_(false) {}
 
 	inline std::string name() const
 	{
@@ -390,7 +492,7 @@ private:
 				for (++argv; *argv; ++argv)
 					tree.printArg(visual(*argv));
 
-			std::printf("\n");
+			tree.done();
 		}
 	}
 
@@ -495,7 +597,7 @@ static Type value(char *program, option options[], bool *success = NULL)
 	return value;
 }
 
-static int options(int argc, char *argv[], pid_t &hpid, pid_t &pid, char *&user)
+static uint16_t options(int argc, char *argv[], pid_t &hpid, pid_t &pid, char *&user)
 {
 	option options[] = {
 		{ "arguments", no_argument, NULL, 'a' },
@@ -518,7 +620,8 @@ static int options(int argc, char *argv[], pid_t &hpid, pid_t &pid, char *&user)
 		{ "user", required_argument, NULL, 0 },
 		{ NULL, 0, NULL, 0 }
 	};
-	int option, index, flags(0);
+	int option, index;
+	uint16_t flags(0);
 	char *program(argv[0]);
 
 	while ((option = getopt_long(argc, argv, "aAchH::GklnptuUV", options, &index)) != -1)
@@ -554,7 +657,7 @@ static int options(int argc, char *argv[], pid_t &hpid, pid_t &pid, char *&user)
 		case 'n':
 			flags |= NumericSort; break;
 		case 'p':
-			flags |= ShowPids; break;
+			flags |= Compact | ShowPids; break;
 		case 't':
 			flags |= ShowTitles; break;
 		case 'u':
@@ -621,7 +724,7 @@ int main(int argc, char *argv[])
 {
 	pid_t hpid(-1), pid(-1);
 	char *user(NULL);
-	int flags(options(argc, argv, hpid, pid, user));
+	uint16_t flags(options(argc, argv, hpid, pid, user));
 
 	if (flags & Version)
 	{