VirtualBox

source: vbox/trunk/src/VBox/Debugger/DBGCScreenAscii.cpp@ 94967

Last change on this file since 94967 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.8 KB
Line 
1/* $Id: DBGCScreenAscii.cpp 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * DBGC - Debugger Console, ASCII screen with optional coloring support.
4 */
5
6/*
7 * Copyright (C) 2016-2022 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_DBGC
23#include <VBox/err.h>
24#include <VBox/log.h>
25
26#include <iprt/mem.h>
27#include <iprt/string.h>
28
29#include "DBGCInternal.h"
30
31
32/*********************************************************************************************************************************
33* Defined Constants And Macros *
34*********************************************************************************************************************************/
35
36
37
38/*********************************************************************************************************************************
39* Structures and Typedefs *
40*********************************************************************************************************************************/
41
42/**
43 * Debug console ASCII screen.
44 */
45typedef struct DBGCSCREENINT
46{
47 /** Width of the screen. */
48 uint32_t cchWidth;
49 /** Height of the screen. */
50 uint32_t cchHeight;
51 /** Extra amount of characters at the end of each line (usually terminator). */
52 uint32_t cchStride;
53 /** Pointer to the char buffer. */
54 char *pszScreen;
55 /** Color information for each pixel. */
56 PDBGCSCREENCOLOR paColors;
57} DBGCSCREENINT;
58/** Pointer to an ASCII screen. */
59typedef DBGCSCREENINT *PDBGCSCREENINT;
60
61
62/*********************************************************************************************************************************
63* Internal Functions *
64*********************************************************************************************************************************/
65
66
67/**
68 * Returns the buffer starting at the given position.
69 *
70 * @returns Pointer to the ASCII buffer.
71 * @param pThis The screen.
72 * @param uX Horizontal position.
73 * @param uY Vertical position.
74 */
75DECLINLINE(char *) dbgcScreenAsciiGetBufferAtPos(PDBGCSCREENINT pThis, uint32_t uX, uint32_t uY)
76{
77 AssertReturn(uX < pThis->cchWidth && uY < pThis->cchHeight, NULL);
78 return pThis->pszScreen + (pThis->cchWidth + pThis->cchStride) * uY + uX;
79}
80
81
82/**
83 * Returns the color buffer starting at the given position.
84 *
85 * @returns Pointer to the color buffer.
86 * @param pThis The screen.
87 * @param uX Horizontal position.
88 * @param uY Vertical position.
89 */
90DECLINLINE(PDBGCSCREENCOLOR) dbgcScreenAsciiGetColorBufferAtPos(PDBGCSCREENINT pThis, uint32_t uX, uint32_t uY)
91{
92 AssertReturn(uX < pThis->cchWidth && uY < pThis->cchHeight, NULL);
93 return &pThis->paColors[pThis->cchWidth * uY + uX];
94}
95
96
97/**
98 * Converts the given color the correct escape sequence.
99 *
100 * @returns Pointer to the string containing the escape sequence for the given color.
101 * @param enmColor The color.
102 */
103static const char *dbgcScreenAsciiColorToEscapeSeq(DBGCSCREENCOLOR enmColor)
104{
105 const char *psz = NULL;
106
107 switch (enmColor)
108 {
109 case DBGCSCREENCOLOR_DEFAULT:
110 psz = "\033[0m";
111 break;
112 case DBGCSCREENCOLOR_BLACK:
113 psz = "\033[30m";
114 break;
115 case DBGCSCREENCOLOR_BLACK_BRIGHT:
116 psz = "\033[30;1m";
117 break;
118 case DBGCSCREENCOLOR_RED:
119 psz = "\033[31m";
120 break;
121 case DBGCSCREENCOLOR_RED_BRIGHT:
122 psz = "\033[31;1m";
123 break;
124 case DBGCSCREENCOLOR_GREEN:
125 psz = "\033[32m";
126 break;
127 case DBGCSCREENCOLOR_GREEN_BRIGHT:
128 psz = "\033[32;1m";
129 break;
130 case DBGCSCREENCOLOR_YELLOW:
131 psz = "\033[33m";
132 break;
133 case DBGCSCREENCOLOR_YELLOW_BRIGHT:
134 psz = "\033[33;1m";
135 break;
136 case DBGCSCREENCOLOR_BLUE:
137 psz = "\033[34m";
138 break;
139 case DBGCSCREENCOLOR_BLUE_BRIGHT:
140 psz = "\033[34;1m";
141 break;
142 case DBGCSCREENCOLOR_MAGENTA:
143 psz = "\033[35m";
144 break;
145 case DBGCSCREENCOLOR_MAGENTA_BRIGHT:
146 psz = "\033[35;1m";
147 break;
148 case DBGCSCREENCOLOR_CYAN:
149 psz = "\033[36m";
150 break;
151 case DBGCSCREENCOLOR_CYAN_BRIGHT:
152 psz = "\033[36;1m";
153 break;
154 case DBGCSCREENCOLOR_WHITE:
155 psz = "\033[37m";
156 break;
157 case DBGCSCREENCOLOR_WHITE_BRIGHT:
158 psz = "\033[37;1m";
159 break;
160 default:
161 AssertFailed();
162 }
163
164 return psz;
165}
166
167
168/**
169 * Creates a new ASCII screen for layouting.
170 *
171 * @returns VBox status code.
172 * @param phScreen Where to store the handle to the screen instance on success.
173 * @param cchWidth Width of the screen in characters.
174 * @param cchHeight Height of the screen in characters.
175 */
176DECLHIDDEN(int) dbgcScreenAsciiCreate(PDBGCSCREEN phScreen, uint32_t cchWidth, uint32_t cchHeight)
177{
178 int rc = VINF_SUCCESS;
179
180 PDBGCSCREENINT pThis = (PDBGCSCREENINT)RTMemAllocZ(sizeof(DBGCSCREENINT));
181 if (pThis)
182 {
183 pThis->cchWidth = cchWidth;
184 pThis->cchHeight = cchHeight;
185 pThis->cchStride = 1; /* Zero terminators after every line. */
186 pThis->pszScreen = RTStrAlloc((cchWidth + 1) * cchHeight * sizeof(char));
187 if (RT_LIKELY(pThis->pszScreen))
188 {
189 pThis->paColors = (PDBGCSCREENCOLOR)RTMemAllocZ(cchWidth * cchHeight * sizeof(DBGCSCREENCOLOR));
190 if (RT_LIKELY(pThis->paColors))
191 {
192 memset(pThis->pszScreen, 0, (cchWidth + 1) * cchHeight * sizeof(char));
193 /* Initialize the screen with spaces. */
194 for (uint32_t i = 0; i < cchHeight; i++)
195 dbgcScreenAsciiDrawLineHorizontal(pThis, 0, cchWidth - 1, i, ' ',
196 DBGCSCREENCOLOR_DEFAULT);
197 *phScreen = pThis;
198 }
199 else
200 rc = VERR_NO_MEMORY;
201
202 if (RT_FAILURE(rc))
203 RTStrFree(pThis->pszScreen);
204 }
205 else
206 rc = VERR_NO_STR_MEMORY;
207
208 if (RT_FAILURE(rc))
209 RTMemFree(pThis);
210 }
211 else
212 rc = VERR_NO_MEMORY;
213
214 return rc;
215}
216
217
218/**
219 * Destroys a given ASCII screen.
220 *
221 * @returns nothing.
222 * @param hScreen The screen handle.
223 */
224DECLHIDDEN(void) dbgcScreenAsciiDestroy(DBGCSCREEN hScreen)
225{
226 PDBGCSCREENINT pThis = hScreen;
227 AssertPtrReturnVoid(pThis);
228
229 RTStrFree(pThis->pszScreen);
230 RTMemFree(pThis->paColors);
231 RTMemFree(pThis);
232}
233
234
235/**
236 * Blits the entire screen using the given callback callback.
237 *
238 * @returns VBox status code.
239 * @param hScreen The screen to blit.
240 * @param pfnBlit Blitting callback.
241 * @param pvUser Opaque user data to pass to the dumper callback.
242 * @param fAddColors Flag whether to use the color info inserting
243 * appropriate escape sequences.
244 */
245DECLHIDDEN(int) dbgcScreenAsciiBlit(DBGCSCREEN hScreen, PFNDGCSCREENBLIT pfnBlit, void *pvUser, bool fAddColors)
246{
247 int rc = VINF_SUCCESS;
248 PDBGCSCREENINT pThis = hScreen;
249 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
250
251 if (!fAddColors)
252 {
253 for (uint32_t iY = 0; iY < pThis->cchHeight && RT_SUCCESS(rc); iY++)
254 {
255 /* Play safe and restore line endings. */
256 char *psz = dbgcScreenAsciiGetBufferAtPos(pThis, 0, iY);
257 psz[pThis->cchWidth] = '\0';
258 rc = pfnBlit(psz, pvUser);
259 if (RT_SUCCESS(rc))
260 rc = pfnBlit("\n", pvUser);
261 }
262 }
263 else
264 {
265 for (uint32_t iY = 0; iY < pThis->cchHeight && RT_SUCCESS(rc); iY++)
266 {
267 /* Play safe and restore line endings. */
268 char *psz = dbgcScreenAsciiGetBufferAtPos(pThis, 0, iY);
269 PDBGCSCREENCOLOR pColor = dbgcScreenAsciiGetColorBufferAtPos(pThis, 0, iY);
270 psz[pThis->cchWidth] = '\0';
271
272 /*
273 * Blit only stuff with the same color at once so to be able to inject the
274 * correct color escape sequences.
275 */
276 uint32_t uStartX = 0;
277 while ( uStartX < pThis->cchWidth
278 && RT_SUCCESS(rc))
279 {
280 uint32_t cchWrite = 0;
281 DBGCSCREENCOLOR enmColorStart = *pColor;
282 while ( uStartX + cchWrite < pThis->cchWidth
283 && enmColorStart == *pColor)
284 {
285 pColor++;
286 cchWrite++;
287 }
288
289 const char *pszEsc = dbgcScreenAsciiColorToEscapeSeq(enmColorStart);
290 rc = pfnBlit(pszEsc, pvUser);
291 if (RT_SUCCESS(rc))
292 {
293 char chTmp = psz[cchWrite];
294 psz[cchWrite] = '\0';
295 rc = pfnBlit(psz, pvUser);
296 psz[cchWrite] = chTmp;
297 uStartX += cchWrite;
298 psz += cchWrite;
299 }
300 }
301 rc = pfnBlit("\n", pvUser);
302 }
303
304 /* Restore to default values at the end. */
305 if (RT_SUCCESS(rc))
306 {
307 const char *pszEsc = dbgcScreenAsciiColorToEscapeSeq(DBGCSCREENCOLOR_DEFAULT);
308 rc = pfnBlit(pszEsc, pvUser);
309 }
310 }
311
312 return rc;
313}
314
315
316/**
317 * Draws a single character to the screen at the given coordinates.
318 *
319 * @returns VBox status code.
320 * @param hScreen The screen handle.
321 * @param uX X coordinate.
322 * @param uY Y coordinate.
323 * @param ch Character to draw.
324 * @param enmColor The color to use.
325 */
326DECLHIDDEN(int) dbgcScreenAsciiDrawCharacter(DBGCSCREEN hScreen, uint32_t uX, uint32_t uY, char ch,
327 DBGCSCREENCOLOR enmColor)
328{
329 PDBGCSCREENINT pThis = hScreen;
330 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
331
332 char *psz = dbgcScreenAsciiGetBufferAtPos(pThis, uX, uY);
333 PDBGCSCREENCOLOR pColor = dbgcScreenAsciiGetColorBufferAtPos(pThis, uX, uY);
334 AssertPtrReturn(psz, VERR_INVALID_STATE);
335 AssertPtrReturn(pColor, VERR_INVALID_STATE);
336 AssertReturn(*psz != '\0', VERR_INVALID_STATE);
337
338 *psz = ch;
339 *pColor = enmColor;
340 return VINF_SUCCESS;
341}
342
343
344/**
345 * Draws a vertical line at the given coordinates.
346 *
347 * @returns nothing.
348 * @param hScreen The screen handle.
349 * @param uX X position to draw.
350 * @param uStartY Y position to start drawing.
351 * @param uEndY Y position to draw to (inclusive).
352 * @param ch The character to use for drawing.
353 * @param enmColor The color to use.
354 */
355DECLHIDDEN(int) dbgcScreenAsciiDrawLineVertical(DBGCSCREEN hScreen, uint32_t uX, uint32_t uStartY,
356 uint32_t uEndY, char ch, DBGCSCREENCOLOR enmColor)
357{
358 PDBGCSCREENINT pThis = hScreen;
359 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
360
361 while (uStartY <= uEndY)
362 {
363 char *psz = dbgcScreenAsciiGetBufferAtPos(pThis, uX, uStartY);
364 PDBGCSCREENCOLOR pColor = dbgcScreenAsciiGetColorBufferAtPos(pThis, uX, uStartY);
365 AssertPtrReturn(psz, VERR_INVALID_STATE);
366 AssertPtrReturn(pColor, VERR_INVALID_STATE);
367 *psz = ch;
368 *pColor = enmColor;
369 uStartY++;
370 }
371
372 return VINF_SUCCESS;
373}
374
375
376/**
377 * Draws a horizontal line at the given coordinates.
378 *
379 * @returns VBox status code..
380 * @param hScreen The screen handle.
381 * @param uStartX X position to start drawing.
382 * @param uEndX X position to draw the line to (inclusive).
383 * @param uY Y position.
384 * @param ch The character to use for drawing.
385 * @param enmColor The color to use.
386 */
387DECLHIDDEN(int) dbgcScreenAsciiDrawLineHorizontal(DBGCSCREEN hScreen, uint32_t uStartX, uint32_t uEndX,
388 uint32_t uY, char ch, DBGCSCREENCOLOR enmColor)
389{
390 PDBGCSCREENINT pThis = hScreen;
391 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
392
393 char *psz = dbgcScreenAsciiGetBufferAtPos(pThis, uStartX, uY);
394 PDBGCSCREENCOLOR pColor = dbgcScreenAsciiGetColorBufferAtPos(pThis, uStartX, uY);
395 AssertPtrReturn(psz, VERR_INVALID_STATE);
396 AssertPtrReturn(pColor, VERR_INVALID_STATE);
397
398 memset(psz, ch, uEndX - uStartX + 1);
399 for (unsigned i = 0; i < uEndX - uStartX + 1; i++)
400 pColor[i] = enmColor;
401
402 return VINF_SUCCESS;
403}
404
405
406/**
407 * Draws a given string to the screen.
408 *
409 * @returns VBox status code..
410 * @param hScreen The screen handle.
411 * @param uX X position to start drawing.
412 * @param uY Y position.
413 * @param pszText The string to draw.
414 * @param enmColor The color to use.
415 */
416DECLHIDDEN(int) dbgcScreenAsciiDrawString(DBGCSCREEN hScreen, uint32_t uX, uint32_t uY, const char *pszText,
417 DBGCSCREENCOLOR enmColor)
418{
419 PDBGCSCREENINT pThis = hScreen;
420 size_t cchText = strlen(pszText);
421 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
422 AssertReturn(uX + cchText <= pThis->cchWidth, VERR_OUT_OF_RANGE);
423 AssertReturn(uY < pThis->cchHeight, VERR_OUT_OF_RANGE);
424
425 char *psz = dbgcScreenAsciiGetBufferAtPos(pThis, uX, uY);
426 PDBGCSCREENCOLOR pColor = dbgcScreenAsciiGetColorBufferAtPos(pThis, uX, uY);
427 AssertPtrReturn(psz, VERR_INVALID_STATE);
428 AssertPtrReturn(pColor, VERR_INVALID_STATE);
429
430 memcpy(psz, pszText, cchText);
431
432 for (unsigned i = 0; i < cchText; i++)
433 pColor[i] = enmColor;
434
435 return VINF_SUCCESS;
436}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette