blob: 2401350b1621e2b8f261ddb96f68b9818f3e205f [file] [log] [blame]
/**********************************************************************
* File: debugwin.cpp
* Description: Portable debug window class.
* Author: Ray Smith
* Created: Wed Feb 21 15:36:59 MST 1996
*
* (C) Copyright 1996, Hewlett-Packard Co.
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
** http://www.apache.org/licenses/LICENSE-2.0
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*
**********************************************************************/
#include "mfcpch.h" //precompiled headers
#include <stdarg.h>
#include "debugwin.h"
DLLSYM INT_VAR (debug_lines, 256, "Number of lines in debug window");
#ifndef GRAPHICS_DISABLED
#ifdef __MAC__
#include <ltextedit.h>
#include <lwindow.h>
//#include <console.h>
#define scrl_SCROLLER 101
#define text_FLOWED 100
static LCommander *pCommander = NULL;
#endif
//NT implementation
#if defined(__MSW32__) && !defined(_CONSOLE)
#define ID_DEBUG_MSG 32779
/**********************************************************************
* DEBUG_WIN::DEBUG_WIN
*
* Create a debug window with size according to the arguments.
**********************************************************************/
DEBUG_WIN::DEBUG_WIN( //constructor
const char *title, //of window
inT32 xpos, //initial position
inT32 ypos, //in pixels
inT32 xsize, //initial size
inT32 ysize, //in pixels
inT32 buflines //default scroll size
) {
char cmd[1024];
int parm; //output from scrolrwin
STARTUPINFO start_info; //process control
PROCESS_INFORMATION proc_info; //process ids
SECURITY_ATTRIBUTES security; //for handles
handle = NULL;
shm_hand = NULL;
shm_mem = NULL;
msg_end = NULL;
dbg_process = NULL; //save handles
dbg_thread = NULL;
security.nLength = sizeof (security);
security.lpSecurityDescriptor = NULL;
security.bInheritHandle = TRUE;//make it inheritable
//anonymous
shm_hand = CreateFileMapping ((HANDLE) 0xffffffff, &security, PAGE_READWRITE, 0, 4096, NULL);
if (shm_hand == NULL)
return; //failed
shm_mem = (char *) MapViewOfFile (shm_hand, FILE_MAP_WRITE, 0, 0, 0);
if (shm_mem == NULL)
return;
shm_mem[5] = 0;
sprintf (cmd, "scrolwin.exe %d %d", buflines, shm_hand);
GetStartupInfo(&start_info); //clone our stuff
if (!CreateProcess (NULL, cmd, NULL, NULL, TRUE,
CREATE_NO_WINDOW | DETACHED_PROCESS | CREATE_SUSPENDED,
NULL, NULL, &start_info, &proc_info))
return;
//save handles
dbg_process = proc_info.hProcess;
dbg_thread = proc_info.hThread;
if (ResumeThread (dbg_thread) != 1)
return;
do
Sleep (100);
while (shm_mem[5] == 0); //wait for handle
parm = ((((uinT8) shm_mem[4] << 8) + (uinT8) shm_mem[3] << 8)
+ (uinT8) shm_mem[2] << 8) + (uinT8) shm_mem[1];
handle = (HWND) parm;
if (handle != NULL) {
//setup window
::SetWindowText (handle, title);
::MoveWindow (handle, xpos, ypos, xsize, ysize, TRUE);
::ShowWindow (handle, SW_SHOW);
}
}
/**********************************************************************
* DEBUG_WIN::DEBUG_WIN
*
* Destroy a debug window.
**********************************************************************/
DEBUG_WIN::~DEBUG_WIN (
//destructor
) {
if (IsWindow (handle))
::SendMessage (handle, WM_COMMAND, IDOK, 0);
if (shm_mem != NULL)
UnmapViewOfFile(shm_mem);
if (shm_hand != NULL)
CloseHandle(shm_hand);
if (dbg_thread != NULL)
CloseHandle(dbg_thread);
if (dbg_process == NULL)
CloseHandle(dbg_process);
}
/**********************************************************************
* dprintf
*
* Print a message to the debug window.
* Like printf, this function can cope with messages which do not end
* in newline, but nothing is printed until the newline is received.
**********************************************************************/
void
DEBUG_WIN::dprintf ( //debug printf
const char *format, ... //special message
) {
va_list args; //variable args
char *msg_start; //for printing
if (!IsWindow (handle))
return; //destroyed
if (msg_end == NULL)
msg_end = shm_mem + 1;
va_start(args, format); //variable list
//Format into msg
vsprintf(msg_end, format, args);
va_end(args);
if (*msg_end == '\0')
return;
msg_start = shm_mem + 1;
do {
//end of line
msg_end = strchr (msg_start, '\n');
if (msg_end == NULL) {
if (msg_start != shm_mem + 1)
//bring to front
strcpy (shm_mem + 1, msg_start);
//current end
msg_end = shm_mem + 1 + strlen (shm_mem + 1);
return;
}
*msg_end = '\0';
while (IsWindow (handle) && shm_mem[0])
Sleep (500);
if (IsWindow (handle)) {
//Visual C++2.0 macro
::SendMessage (handle, WM_COMMAND, ID_DEBUG_MSG, (DWORD) (msg_start - shm_mem));
}
msg_start = msg_end + 1;
}
while (*msg_start != '\0');
msg_end = shm_mem + 1; //buffer empty
}
/**********************************************************************
* await_destruction
*
* Wait for the user to close the debug window. Then return.
**********************************************************************/
void DEBUG_WIN::await_destruction() { //wait for user to close
WaitForSingleObject (dbg_process, (unsigned long) -1);
}
#endif //NT Implmentation
//UNIX implementation
#if defined(__UNIX__) || defined(_CONSOLE)
#ifdef __UNIX__
#include <unistd.h>
#include <signal.h>
#endif
//#include "basefile.h"
/**********************************************************************
* DEBUG_WIN::DEBUG_WIN
*
* Create a debug window with size according to the arguments.
* Create an hpterm window with a pipe connected to it.
**********************************************************************/
DEBUG_WIN::DEBUG_WIN( //constructor
const char *title, //of window
inT32 xpos, //initial position
inT32 ypos, //in pixels
inT32 xsize, //initial size
inT32 ysize, //in pixels
inT32 buflines //default scroll size
) {
#ifdef __UNIX__
inT32 length; /*length of name */
char command[MAX_PATH]; /*pipe command */
pid_t pid; /*process id */
char host[MAX_PATH]; //remote host
BOOL8 remote; //remote host
// remote=remote_display(host); //check remote host
remote = FALSE;
if (remote)
//do it remotely
length = sprintf (command, "remsh %s 'DISPLAY=%s;export DISPLAY;", host, getenv ("DISPLAY"));
else
length = 0;
length += sprintf (command + length, "trap \"\" 1 2 3 13 15\n");
length +=
sprintf (command + length,
"/usr/bin/xterm -sb -sl " INT32FORMAT " -geometry "
INT32FORMAT "x" INT32FORMAT "", buflines, xsize / 8, ysize / 16);
if (xpos >= 0)
command[length++] = '+';
length += sprintf (command + length, INT32FORMAT, xpos);
if (ypos >= 0)
command[length++] = '+';
length +=
sprintf (command + length,
INT32FORMAT " -title \"%s\" -n \"%s\" -e /bin/sh -c ", ypos,
title, title);
pid = getpid (); /*random number */
length +=
sprintf (command + length,
"\"stty opost; tty >/tmp/debug%d; while [ -s /tmp/debug%d ]\ndo\nsleep 1\ndone\" &\n",
pid, pid);
length +=
sprintf (command + length, "trap \"rm -f /tmp/debug%d; kill -9 $!\" 0\n",
pid);
length += sprintf (command + length, "trap \"exit\" 1 2 3 13 15\n");
length +=
sprintf (command + length,
"while [ ! -s /tmp/debug%d ]\ndo\nsleep 1\ndone\n", pid);
length += sprintf (command + length, "trap \"\" 1 2 3 13 15\n");
length += sprintf (command + length, "ofile=`cat /tmp/debug%d`\n", pid);
length +=
sprintf (command + length, "cat -u - >$ofile; rm /tmp/debug%d\n", pid);
if (remote) {
command[length++] = '\''; //terminate remsh
command[length] = '\0';
}
fp = popen (command, "w"); /*create window */
if (fp != NULL) {
/*set no buffering */
if (setvbuf (fp, NULL, _IONBF, BUFSIZ)) {
pclose(fp);
fp = NULL;
}
}
#endif
}
/**********************************************************************
* DEBUG_WIN::DEBUG_WIN
*
* Close the file and destroy the window.
**********************************************************************/
DEBUG_WIN::~DEBUG_WIN (
//destructor
) {
#ifdef __UNIX__
pclose(fp);
#endif
}
/**********************************************************************
* dprintf
*
* Print a message to the debug window.
* Like printf, this function can cope with messages which do not end
* in newline, but nothing is printed until the newline is received.
**********************************************************************/
void
DEBUG_WIN::dprintf ( //debug printf
const char *format, ... //special message
) {
va_list args; //variable args
va_start(args, format); //variable list
#ifdef __UNIX__
vfprintf(fp, format, args); //Format into msg
#else
//Format into msg
vfprintf(stderr, format, args);
#endif
va_end(args);
}
/**********************************************************************
* await_destruction
*
* Wait for the user to close the debug window. Then return.
**********************************************************************/
void DEBUG_WIN::await_destruction() { //wait for user to close
#ifdef __UNIX__
signal(SIGPIPE, SIG_IGN);
while (!ferror (fp)) {
sleep (1);
fputc (0, fp); //send nulls until error
}
#endif
}
#endif //UNIX Implmentation
#ifdef __MAC__ //NT implementation
#include <stdio.h>
//#include "textwindow.h"
#include <lwindow.h>
#include "ipcbase.h" //must be last include
// Until I can figure a way to do this without linking in PowerPlant,
// the debug window will just have empty functions so compilation can take place.
/**********************************************************************
* DEBUG_WIN::SetCommander
*
* Mac-specific function to set the commander for the next debug window
**********************************************************************/
void DEBUG_WIN::SetCommander(LCommander *pNew) {
pCommander = pNew;
}
/**********************************************************************
* DEBUG_WIN::DEBUG_WIN
*
* Create a debug window with size according to the arguments.
* Create an hpterm window with a pipe connected to it.
**********************************************************************/
DEBUG_WIN::DEBUG_WIN( //constructor
const char *title, //of window
inT32 xpos, //initial position
inT32 ypos, //in pixels
inT32 xsize, //initial size
inT32 ysize, //in pixels
inT32 buflines //default scroll size
) {
inT32 length; /*length of name */
// don't replace this DebugStr() with a call to DEBUG_WIN!
//if (pCommander==NULL) DebugStr("\pDEBUG_WIN::DEBUG_WIN(), Commander not set");
// create the window
//pWindow=LWindow::CreateWindow(2700,pCommander);
}
/**********************************************************************
* DEBUG_WIN::DEBUG_WIN
*
* Close the file and destroy the window.
**********************************************************************/
DEBUG_WIN::~DEBUG_WIN (
//destructor
) {
}
/**********************************************************************
* dprintf
*
* Print a message to the debug window.
* Like printf, this function can cope with messages which do not end
* in newline, but nothing is printed until the newline is received.
**********************************************************************/
void
DEBUG_WIN::dprintf ( //debug printf
const char *format, ... //special message
) {
#if 0
LTextEdit *pTextEdit;
va_list args; //variable args
static char msg[1024];
inT32 i;
inT32 OriginalLength;
inT32 NewLength;
TEHandle hTextEdit;
char *pTempBuffer;
CharsHandle hChar;
char *pOriginalText;
inT32 StringLength;
pTextEdit = (LTextEdit *) pWindow->FindPaneByID (text_FLOWED);
if (pTextEdit == NULL)
DebugStr ("\pwhoops");
// get a C String from the format and args passed in
va_start(args, format); //variable list
vsprintf(msg, format, args); //Format into msg
va_end(args);
StringLength = strlen (msg);
// get the handle for the text
hTextEdit = pTextEdit->GetMacTEH ();
if (hTextEdit == NULL)
DebugStr ("\pDEBUG_WIN,WriteCharsToConsole()");
// get a pointer to the characters and the length of the character stream
hChar = TEGetText (hTextEdit);
if (hChar == NULL)
DebugStr ("\pDEBUG_WIN,WriteCharsToConsole()");
pOriginalText = *hChar; // get pointer to existing text
// get the length of the original data
OriginalLength = (*hTextEdit)->teLength;
// setup a temporary buffer for the new text
NewLength = OriginalLength + StringLength;
pTempBuffer = NewPtr (NewLength);
if (pTempBuffer == NULL)
DebugStr ("\pDEBUG_WIN,WriteCharsToConsole()");
// copy the original data into the new buffer
for (i = 0; i < OriginalLength; i++)
pTempBuffer[i] = pOriginalText[i];
// append the new data onto the end of the original buffer
for (i = 0; i < StringLength; i++) {
if (msg[i] == '\n')
pTempBuffer[i + OriginalLength] = '\r';
else
pTempBuffer[i + OriginalLength] = msg[i];
}
// put the new text into the text edit item
TESetText(pTempBuffer, NewLength, hTextEdit);
// clean up
DisposePtr(pTempBuffer);
#endif
}
#endif //Mac Implmentation
#else // Non graphical debugger
DEBUG_WIN::DEBUG_WIN( const char*, inT32, inT32, inT32, inT32, inT32 ) {
}
DEBUG_WIN::~DEBUG_WIN () {
}
void DEBUG_WIN::dprintf (const char *format, ...) {
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
}
void await_destruction() {
}
#endif