xref: /haiku/src/apps/serialconnect/TermView.cpp (revision f73f5d4c42a01ece688cbb57b5d332cc0f68b2c6)
1 /*
2  * Copyright 2012, Adrien Destugues, pulkomandy@gmail.com
3  * Distributed under the terms of the MIT licence.
4  */
5 
6 
7 #include "TermView.h"
8 
9 #include <stdio.h>
10 
11 #include <Entry.h>
12 #include <File.h>
13 #include <Layout.h>
14 
15 #include "SerialApp.h"
16 
17 
18 TermView::TermView()
19 	:
20 	BView("TermView", B_WILL_DRAW | B_FRAME_EVENTS)
21 {
22 	font_height height;
23 	GetFontHeight(&height);
24 	fFontHeight = height.ascent + height.descent + height.leading;
25 	fFontWidth = be_fixed_font->StringWidth("X");
26 	fTerm = vterm_new(kDefaultHeight, kDefaultWidth);
27 
28 	vterm_parser_set_utf8(fTerm, 1);
29 
30 	fTermScreen = vterm_obtain_screen(fTerm);
31 	vterm_screen_set_callbacks(fTermScreen, &sScreenCallbacks, this);
32 	vterm_screen_reset(fTermScreen, 1);
33 
34 	SetFont(be_fixed_font);
35 }
36 
37 
38 TermView::~TermView()
39 {
40 	vterm_free(fTerm);
41 }
42 
43 
44 void TermView::AttachedToWindow()
45 {
46 	MakeFocus();
47 }
48 
49 
50 void TermView::Draw(BRect updateRect)
51 {
52 	VTermRect updatedChars = PixelsToGlyphs(updateRect);
53 
54 	VTermPos pos;
55 	font_height height;
56 	GetFontHeight(&height);
57 
58 	int availableRows, availableCols;
59 	vterm_get_size(fTerm, &availableRows, &availableCols);
60 
61 	for (pos.row = updatedChars.start_row; pos.row <= updatedChars.end_row;
62 			pos.row++) {
63 		float x = updatedChars.start_col * fFontWidth + kBorderSpacing;
64 		float y = pos.row * fFontHeight + height.ascent + kBorderSpacing;
65 		MovePenTo(x, y);
66 
67 		for (pos.col = updatedChars.start_col;
68 				pos.col <= updatedChars.end_col;) {
69 			if (pos.col < 0 || pos.row < 0 || pos.col >= availableCols
70 					|| pos.row >= availableRows) {
71 				DrawString(" ");
72 				pos.col ++;
73 			} else {
74 				VTermScreenCell cell;
75 				vterm_screen_get_cell(fTermScreen, pos, &cell);
76 
77 				rgb_color foreground, background;
78 				foreground.red = cell.fg.red;
79 				foreground.green = cell.fg.green;
80 				foreground.blue = cell.fg.blue;
81 				background.red = cell.bg.red;
82 				background.green = cell.bg.green;
83 				background.blue = cell.bg.blue;
84 
85 				if(cell.attrs.reverse) {
86 					SetLowColor(foreground);
87 					SetViewColor(foreground);
88 					SetHighColor(background);
89 				} else {
90 					SetLowColor(background);
91 					SetViewColor(background);
92 					SetHighColor(foreground);
93 				}
94 
95 				BPoint penLocation = PenLocation();
96 				FillRect(BRect(penLocation.x, penLocation.y - height.ascent,
97 					penLocation.x + cell.width * fFontWidth, penLocation.y), B_SOLID_LOW);
98 
99 				if (cell.chars[0] == 0) {
100 					DrawString(" ");
101 					pos.col ++;
102 				} else {
103 					char buffer[VTERM_MAX_CHARS_PER_CELL];
104 					wcstombs(buffer, (wchar_t*)cell.chars,
105 						VTERM_MAX_CHARS_PER_CELL);
106 
107 					DrawString(buffer);
108 					pos.col += cell.width;
109 				}
110 			}
111 		}
112 	}
113 }
114 
115 
116 void TermView::FrameResized(float width, float height)
117 {
118 	VTermRect newSize = PixelsToGlyphs(BRect(0, 0, width - 2 * kBorderSpacing,
119 		height - 2 * kBorderSpacing));
120 	vterm_set_size(fTerm, newSize.end_row, newSize.end_col);
121 }
122 
123 
124 void TermView::GetPreferredSize(float* width, float* height)
125 {
126 	if (width != NULL)
127 		*width = kDefaultWidth * fFontWidth + 2 * kBorderSpacing;
128 	if (height != NULL)
129 		*height = kDefaultHeight * fFontHeight + 2 * kBorderSpacing;
130 }
131 
132 
133 void TermView::KeyDown(const char* bytes, int32 numBytes)
134 {
135 	BMessage* keyEvent = new BMessage(kMsgDataWrite);
136 	keyEvent->AddData("data", B_RAW_TYPE, bytes, numBytes);
137 	be_app_messenger.SendMessage(keyEvent);
138 }
139 
140 
141 void TermView::MessageReceived(BMessage* message)
142 {
143 	switch(message->what)
144 	{
145 		case 'DATA':
146 		{
147 			entry_ref ref;
148 			if(message->FindRef("refs", &ref) == B_OK)
149 			{
150 				// The user just dropped a file on us
151 				// TODO send it by XMODEM or so
152 			}
153 			break;
154 		}
155 		default:
156 			BView::MessageReceived(message);
157 	}
158 }
159 
160 
161 void TermView::PushBytes(const char* bytes, size_t length)
162 {
163 	vterm_push_bytes(fTerm, bytes, length);
164 }
165 
166 
167 //#pragma mark -
168 
169 
170 VTermRect TermView::PixelsToGlyphs(BRect pixels) const
171 {
172 	pixels.OffsetBy(-kBorderSpacing, -kBorderSpacing);
173 
174 	VTermRect rect;
175 	rect.start_col = (int)floor(pixels.left / fFontWidth);
176 	rect.end_col = (int)ceil(pixels.right / fFontWidth);
177 	rect.start_row = (int)floor(pixels.top / fFontHeight);
178 	rect.end_row = (int)ceil(pixels.bottom / fFontHeight);
179 /*
180 	printf(
181 		"TOP %d ch < %f px\n"
182 		"BTM %d ch < %f px\n"
183 		"LFT %d ch < %f px\n"
184 		"RGH %d ch < %f px\n",
185 		rect.start_row, pixels.top,
186 		rect.end_row, pixels.bottom,
187 		rect.start_col, pixels.left,
188 		rect.end_col, pixels.right
189 	);
190 */
191 	return rect;
192 }
193 
194 
195 BRect TermView::GlyphsToPixels(const VTermRect& glyphs) const
196 {
197 	BRect rect;
198 	rect.top = glyphs.start_row * fFontHeight;
199 	rect.bottom = glyphs.end_row * fFontHeight;
200 	rect.left = glyphs.start_col * fFontWidth;
201 	rect.right = glyphs.end_col * fFontWidth;
202 
203 	rect.OffsetBy(kBorderSpacing, kBorderSpacing);
204 /*
205 	printf(
206 		"TOP %d ch > %f px (%f)\n"
207 		"BTM %d ch > %f px\n"
208 		"LFT %d ch > %f px (%f)\n"
209 		"RGH %d ch > %f px\n",
210 		glyphs.start_row, rect.top, fFontHeight,
211 		glyphs.end_row, rect.bottom,
212 		glyphs.start_col, rect.left, fFontWidth,
213 		glyphs.end_col, rect.right
214 	);
215 */
216 	return rect;
217 }
218 
219 
220 BRect TermView::GlyphsToPixels(const int width, const int height) const
221 {
222 	VTermRect rect;
223 	rect.start_row = 0;
224 	rect.start_col = 0;
225 	rect.end_row = height;
226 	rect.end_col = width;
227 	return GlyphsToPixels(rect);
228 }
229 
230 
231 void TermView::Damage(VTermRect rect)
232 {
233 	Invalidate();
234 //	Invalidate(GlyphsToPixels(rect));
235 }
236 
237 
238 /* static */
239 int TermView::Damage(VTermRect rect, void* user)
240 {
241 	TermView* view = (TermView*)user;
242 	view->Damage(rect);
243 
244 	return 0;
245 }
246 
247 
248 const VTermScreenCallbacks TermView::sScreenCallbacks = {
249 	&TermView::Damage,
250 	/*.moverect =*/ NULL,
251 	/*.movecursor =*/ NULL,
252 	/*.settermprop =*/ NULL,
253 	/*.setmousefunc =*/ NULL,
254 	/*.bell =*/ NULL,
255 	/*.resize =*/ NULL,
256 };
257