VirtualBox

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

Last change on this file since 97364 was 96407, checked in by vboxsync, 2 years ago

scm copyright and license note update

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