VirtualBox

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

Last change on this file since 65521 was 65118, checked in by vboxsync, 8 years ago

Debugger: doxygen fixes

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