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 <Layout.h> 12 13 #include "SerialApp.h" 14 15 16 TermView::TermView() 17 : 18 BView("TermView", B_WILL_DRAW) 19 { 20 font_height height; 21 GetFontHeight(&height); 22 fFontHeight = height.ascent + height.descent + height.leading; 23 fFontWidth = be_fixed_font->StringWidth("X"); 24 fTerm = vterm_new(kDefaultHeight, kDefaultWidth); 25 26 vterm_parser_set_utf8(fTerm, 1); 27 28 fTermScreen = vterm_obtain_screen(fTerm); 29 vterm_screen_set_callbacks(fTermScreen, &sScreenCallbacks, this); 30 vterm_screen_reset(fTermScreen, 1); 31 32 SetFont(be_fixed_font); 33 } 34 35 36 TermView::~TermView() 37 { 38 vterm_free(fTerm); 39 } 40 41 42 void TermView::AttachedToWindow() 43 { 44 MakeFocus(); 45 } 46 47 48 void TermView::Draw(BRect updateRect) 49 { 50 VTermRect updatedChars = PixelsToGlyphs(updateRect); 51 52 VTermPos pos; 53 font_height height; 54 GetFontHeight(&height); 55 for (pos.row = updatedChars.start_row; pos.row <= updatedChars.end_row; 56 pos.row++) { 57 float x = updatedChars.start_col * fFontWidth + kBorderSpacing; 58 float y = pos.row * fFontHeight + height.ascent + kBorderSpacing; 59 MovePenTo(x, y); 60 61 for (pos.col = updatedChars.start_col; 62 pos.col <= updatedChars.end_col;) { 63 if (pos.col < 0 || pos.row < 0 || pos.col >= kDefaultWidth 64 || pos.row >= kDefaultHeight) { 65 DrawString(" "); 66 pos.col ++; 67 } else { 68 VTermScreenCell cell; 69 vterm_screen_get_cell(fTermScreen, pos, &cell); 70 71 if (cell.chars[0] == 0) { 72 DrawString(" "); 73 pos.col ++; 74 } else { 75 char buffer[VTERM_MAX_CHARS_PER_CELL]; 76 wcstombs(buffer, (wchar_t*)cell.chars, 77 VTERM_MAX_CHARS_PER_CELL); 78 79 DrawString(buffer); 80 pos.col += cell.width; 81 } 82 } 83 } 84 } 85 } 86 87 88 void TermView::GetPreferredSize(float* width, float* height) 89 { 90 if (width != NULL) 91 *width = kDefaultWidth * fFontWidth + 2 * kBorderSpacing; 92 if (height != NULL) 93 *height = kDefaultHeight * fFontHeight + 2 * kBorderSpacing; 94 } 95 96 97 void TermView::KeyDown(const char* bytes, int32 numBytes) 98 { 99 BMessage* keyEvent = new BMessage(kMsgDataWrite); 100 keyEvent->AddData("data", B_RAW_TYPE, bytes, numBytes); 101 be_app_messenger.SendMessage(keyEvent); 102 } 103 104 105 void TermView::PushBytes(const char* bytes, size_t length) 106 { 107 vterm_push_bytes(fTerm, bytes, length); 108 } 109 110 111 VTermRect TermView::PixelsToGlyphs(BRect pixels) const 112 { 113 pixels.OffsetBy(-kBorderSpacing, -kBorderSpacing); 114 115 VTermRect rect; 116 rect.start_col = (int)floor(pixels.left / fFontWidth); 117 rect.end_col = (int)ceil(pixels.right / fFontWidth); 118 rect.start_row = (int)floor(pixels.top / fFontHeight); 119 rect.end_row = (int)ceil(pixels.bottom / fFontHeight); 120 /* 121 printf( 122 "TOP %d ch < %f px\n" 123 "BTM %d ch < %f px\n" 124 "LFT %d ch < %f px\n" 125 "RGH %d ch < %f px\n", 126 rect.start_row, pixels.top, 127 rect.end_row, pixels.bottom, 128 rect.start_col, pixels.left, 129 rect.end_col, pixels.right 130 ); 131 */ 132 return rect; 133 } 134 135 136 BRect TermView::GlyphsToPixels(const VTermRect& glyphs) const 137 { 138 BRect rect; 139 rect.top = glyphs.start_row * fFontHeight; 140 rect.bottom = glyphs.end_row * fFontHeight; 141 rect.left = glyphs.start_col * fFontWidth; 142 rect.right = glyphs.end_col * fFontWidth; 143 144 rect.OffsetBy(kBorderSpacing, kBorderSpacing); 145 /* 146 printf( 147 "TOP %d ch > %f px (%f)\n" 148 "BTM %d ch > %f px\n" 149 "LFT %d ch > %f px (%f)\n" 150 "RGH %d ch > %f px\n", 151 glyphs.start_row, rect.top, fFontHeight, 152 glyphs.end_row, rect.bottom, 153 glyphs.start_col, rect.left, fFontWidth, 154 glyphs.end_col, rect.right 155 ); 156 */ 157 return rect; 158 } 159 160 161 BRect TermView::GlyphsToPixels(const int width, const int height) const 162 { 163 VTermRect rect; 164 rect.start_row = 0; 165 rect.start_col = 0; 166 rect.end_row = height; 167 rect.end_col = width; 168 return GlyphsToPixels(rect); 169 } 170 171 172 void TermView::Damage(VTermRect rect) 173 { 174 Invalidate(); 175 // Invalidate(GlyphsToPixels(rect)); 176 } 177 178 179 /* static */ 180 int TermView::Damage(VTermRect rect, void* user) 181 { 182 TermView* view = (TermView*)user; 183 view->Damage(rect); 184 185 return 0; 186 } 187 188 189 const VTermScreenCallbacks TermView::sScreenCallbacks = { 190 &TermView::Damage, 191 /*.moverect =*/ NULL, 192 /*.movecursor =*/ NULL, 193 /*.settermprop =*/ NULL, 194 /*.setmousefunc =*/ NULL, 195 /*.bell =*/ NULL, 196 /*.resize =*/ NULL, 197 }; 198