• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**********************************************************************
2  * File:        debugwin.cpp
3  * Description: Portable debug window class.
4  * Author:      Ray Smith
5  * Created:     Wed Feb 21 15:36:59 MST 1996
6  *
7  * (C) Copyright 1996, Hewlett-Packard Co.
8  ** Licensed under the Apache License, Version 2.0 (the "License");
9  ** you may not use this file except in compliance with the License.
10  ** You may obtain a copy of the License at
11  ** http://www.apache.org/licenses/LICENSE-2.0
12  ** Unless required by applicable law or agreed to in writing, software
13  ** distributed under the License is distributed on an "AS IS" BASIS,
14  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  ** See the License for the specific language governing permissions and
16  ** limitations under the License.
17  *
18  **********************************************************************/
19 
20 #include          "mfcpch.h"     //precompiled headers
21 #include          <stdarg.h>
22 #include          "debugwin.h"
23 
24 DLLSYM INT_VAR (debug_lines, 256, "Number of lines in debug window");
25 
26 #ifndef GRAPHICS_DISABLED
27 
28 #ifdef __MAC__
29 #include          <ltextedit.h>
30 #include          <lwindow.h>
31 //#include                                              <console.h>
32 
33 #define scrl_SCROLLER   101
34 #define text_FLOWED     100
35 
36 static LCommander *pCommander = NULL;
37 #endif
38 
39                                  //NT implementation
40 #if defined(__MSW32__) && !defined(_CONSOLE)
41 
42 #define ID_DEBUG_MSG       32779
43 
44 /**********************************************************************
45  * DEBUG_WIN::DEBUG_WIN
46  *
47  * Create a debug window with size according to the arguments.
48  **********************************************************************/
49 
DEBUG_WIN(const char * title,inT32 xpos,inT32 ypos,inT32 xsize,inT32 ysize,inT32 buflines)50 DEBUG_WIN::DEBUG_WIN(                    //constructor
51                      const char *title,  //of window
52                      inT32 xpos,         //initial position
53                      inT32 ypos,         //in pixels
54                      inT32 xsize,        //initial size
55                      inT32 ysize,        //in pixels
56                      inT32 buflines      //default scroll size
57                     ) {
58   char cmd[1024];
59   int parm;                      //output from scrolrwin
60   STARTUPINFO start_info;        //process control
61   PROCESS_INFORMATION proc_info; //process ids
62   SECURITY_ATTRIBUTES security;  //for handles
63 
64   handle = NULL;
65   shm_hand = NULL;
66   shm_mem = NULL;
67   msg_end = NULL;
68   dbg_process = NULL;            //save handles
69   dbg_thread = NULL;
70   security.nLength = sizeof (security);
71   security.lpSecurityDescriptor = NULL;
72   security.bInheritHandle = TRUE;//make it inheritable
73                                  //anonymous
74   shm_hand = CreateFileMapping ((HANDLE) 0xffffffff, &security, PAGE_READWRITE, 0, 4096, NULL);
75   if (shm_hand == NULL)
76     return;                      //failed
77   shm_mem = (char *) MapViewOfFile (shm_hand, FILE_MAP_WRITE, 0, 0, 0);
78   if (shm_mem == NULL)
79     return;
80   shm_mem[5] = 0;
81   sprintf (cmd, "scrolwin.exe %d %d", buflines, shm_hand);
82   GetStartupInfo(&start_info);  //clone our stuff
83   if (!CreateProcess (NULL, cmd, NULL, NULL, TRUE,
84     CREATE_NO_WINDOW | DETACHED_PROCESS | CREATE_SUSPENDED,
85     NULL, NULL, &start_info, &proc_info))
86     return;
87 
88                                  //save handles
89   dbg_process = proc_info.hProcess;
90   dbg_thread = proc_info.hThread;
91   if (ResumeThread (dbg_thread) != 1)
92     return;
93   do
94   Sleep (100);
95   while (shm_mem[5] == 0);       //wait for handle
96   parm = ((((uinT8) shm_mem[4] << 8) + (uinT8) shm_mem[3] << 8)
97     + (uinT8) shm_mem[2] << 8) + (uinT8) shm_mem[1];
98   handle = (HWND) parm;
99   if (handle != NULL) {
100                                  //setup window
101     ::SetWindowText (handle, title);
102     ::MoveWindow (handle, xpos, ypos, xsize, ysize, TRUE);
103     ::ShowWindow (handle, SW_SHOW);
104   }
105 }
106 
107 
108 /**********************************************************************
109  * DEBUG_WIN::DEBUG_WIN
110  *
111  * Destroy a debug window.
112  **********************************************************************/
113 
~DEBUG_WIN()114 DEBUG_WIN::~DEBUG_WIN (
115 //destructor
116 ) {
117   if (IsWindow (handle))
118     ::SendMessage (handle, WM_COMMAND, IDOK, 0);
119   if (shm_mem != NULL)
120     UnmapViewOfFile(shm_mem);
121   if (shm_hand != NULL)
122     CloseHandle(shm_hand);
123   if (dbg_thread != NULL)
124     CloseHandle(dbg_thread);
125   if (dbg_process == NULL)
126     CloseHandle(dbg_process);
127 
128 }
129 
130 
131 /**********************************************************************
132  * dprintf
133  *
134  * Print a message to the debug window.
135  * Like printf, this function can cope with messages which do not end
136  * in newline, but nothing is printed until the newline is received.
137  **********************************************************************/
138 
139 void
dprintf(const char * format,...)140 DEBUG_WIN::dprintf (             //debug printf
141 const char *format, ...          //special message
142 ) {
143   va_list args;                  //variable args
144   char *msg_start;               //for printing
145 
146   if (!IsWindow (handle))
147     return;                      //destroyed
148   if (msg_end == NULL)
149     msg_end = shm_mem + 1;
150   va_start(args, format);  //variable list
151                                  //Format into msg
152   vsprintf(msg_end, format, args);
153   va_end(args);
154   if (*msg_end == '\0')
155     return;
156   msg_start = shm_mem + 1;
157   do {
158                                  //end of line
159     msg_end = strchr (msg_start, '\n');
160     if (msg_end == NULL) {
161       if (msg_start != shm_mem + 1)
162                                  //bring to front
163         strcpy (shm_mem + 1, msg_start);
164                                  //current end
165       msg_end = shm_mem + 1 + strlen (shm_mem + 1);
166       return;
167     }
168     *msg_end = '\0';
169     while (IsWindow (handle) && shm_mem[0])
170       Sleep (500);
171     if (IsWindow (handle)) {
172                                  //Visual C++2.0 macro
173       ::SendMessage (handle, WM_COMMAND, ID_DEBUG_MSG, (DWORD) (msg_start - shm_mem));
174     }
175     msg_start = msg_end + 1;
176   }
177   while (*msg_start != '\0');
178   msg_end = shm_mem + 1;         //buffer empty
179 }
180 
181 
182 /**********************************************************************
183  * await_destruction
184  *
185  * Wait for the user to close the debug window. Then return.
186  **********************************************************************/
187 
await_destruction()188 void DEBUG_WIN::await_destruction() {  //wait for user to close
189   WaitForSingleObject (dbg_process, (unsigned long) -1);
190 }
191 #endif                           //NT Implmentation
192 
193                                  //UNIX implementation
194 #if defined(__UNIX__) || defined(_CONSOLE)
195 #ifdef __UNIX__
196 #include          <unistd.h>
197 #include          <signal.h>
198 #endif
199 //#include                                      "basefile.h"
200 
201 /**********************************************************************
202  * DEBUG_WIN::DEBUG_WIN
203  *
204  * Create a debug window with size according to the arguments.
205  * Create an hpterm window with a pipe connected to it.
206  **********************************************************************/
207 
DEBUG_WIN(const char * title,inT32 xpos,inT32 ypos,inT32 xsize,inT32 ysize,inT32 buflines)208 DEBUG_WIN::DEBUG_WIN(                    //constructor
209                      const char *title,  //of window
210                      inT32 xpos,         //initial position
211                      inT32 ypos,         //in pixels
212                      inT32 xsize,        //initial size
213                      inT32 ysize,        //in pixels
214                      inT32 buflines      //default scroll size
215                     ) {
216   #ifdef __UNIX__
217   inT32 length;                  /*length of name */
218   char command[MAX_PATH];        /*pipe command */
219   pid_t pid;                     /*process id */
220   char host[MAX_PATH];           //remote host
221   BOOL8 remote;                  //remote host
222 
223   //      remote=remote_display(host);                                                                    //check remote host
224   remote = FALSE;
225   if (remote)
226                                  //do it remotely
227     length = sprintf (command, "remsh %s 'DISPLAY=%s;export DISPLAY;", host, getenv ("DISPLAY"));
228   else
229     length = 0;
230   length += sprintf (command + length, "trap \"\" 1 2 3 13 15\n");
231   length +=
232     sprintf (command + length,
233     "/usr/bin/xterm -sb -sl " INT32FORMAT " -geometry "
234     INT32FORMAT "x" INT32FORMAT "", buflines, xsize / 8, ysize / 16);
235   if (xpos >= 0)
236     command[length++] = '+';
237   length += sprintf (command + length, INT32FORMAT, xpos);
238   if (ypos >= 0)
239     command[length++] = '+';
240   length +=
241     sprintf (command + length,
242     INT32FORMAT " -title \"%s\" -n \"%s\" -e /bin/sh -c ", ypos,
243     title, title);
244   pid = getpid ();               /*random number */
245   length +=
246     sprintf (command + length,
247     "\"stty opost; tty >/tmp/debug%d; while [ -s /tmp/debug%d ]\ndo\nsleep 1\ndone\" &\n",
248     pid, pid);
249   length +=
250     sprintf (command + length, "trap \"rm -f /tmp/debug%d; kill -9 $!\" 0\n",
251     pid);
252   length += sprintf (command + length, "trap \"exit\" 1 2 3 13 15\n");
253   length +=
254     sprintf (command + length,
255     "while [ ! -s /tmp/debug%d ]\ndo\nsleep 1\ndone\n", pid);
256   length += sprintf (command + length, "trap \"\" 1 2 3 13 15\n");
257   length += sprintf (command + length, "ofile=`cat /tmp/debug%d`\n", pid);
258   length +=
259     sprintf (command + length, "cat -u - >$ofile; rm /tmp/debug%d\n", pid);
260   if (remote) {
261     command[length++] = '\'';    //terminate remsh
262     command[length] = '\0';
263   }
264   fp = popen (command, "w");     /*create window */
265   if (fp != NULL) {
266                                  /*set no buffering */
267     if (setvbuf (fp, NULL, _IONBF, BUFSIZ)) {
268       pclose(fp);
269       fp = NULL;
270     }
271   }
272   #endif
273 }
274 
275 
276 /**********************************************************************
277  * DEBUG_WIN::DEBUG_WIN
278  *
279  * Close the file and destroy the window.
280  **********************************************************************/
281 
~DEBUG_WIN()282 DEBUG_WIN::~DEBUG_WIN (
283 //destructor
284 ) {
285   #ifdef __UNIX__
286   pclose(fp);
287   #endif
288 }
289 
290 
291 /**********************************************************************
292  * dprintf
293  *
294  * Print a message to the debug window.
295  * Like printf, this function can cope with messages which do not end
296  * in newline, but nothing is printed until the newline is received.
297  **********************************************************************/
298 
299 void
dprintf(const char * format,...)300 DEBUG_WIN::dprintf (             //debug printf
301 const char *format, ...          //special message
302 ) {
303   va_list args;                  //variable args
304 
305   va_start(args, format);  //variable list
306   #ifdef __UNIX__
307   vfprintf(fp, format, args);  //Format into msg
308   #else
309                                  //Format into msg
310   vfprintf(stderr, format, args);
311   #endif
312   va_end(args);
313 }
314 
315 
316 /**********************************************************************
317  * await_destruction
318  *
319  * Wait for the user to close the debug window. Then return.
320  **********************************************************************/
321 
await_destruction()322 void DEBUG_WIN::await_destruction() {  //wait for user to close
323   #ifdef __UNIX__
324   signal(SIGPIPE, SIG_IGN);
325   while (!ferror (fp)) {
326     sleep (1);
327     fputc (0, fp);               //send nulls until error
328   }
329   #endif
330 }
331 #endif                           //UNIX Implmentation
332 
333 #ifdef __MAC__                   //NT implementation
334 #include          <stdio.h>
335 //#include                                                      "textwindow.h"
336 #include          <lwindow.h>
337 #include          "ipcbase.h"    //must be last include
338 
339 // Until I can figure a way to do this without linking in PowerPlant,
340 // the debug window will just have empty functions so compilation can take place.
341 
342 /**********************************************************************
343  * DEBUG_WIN::SetCommander
344  *
345  * Mac-specific function to set the commander for the next debug window
346  **********************************************************************/
SetCommander(LCommander * pNew)347 void DEBUG_WIN::SetCommander(LCommander *pNew) {
348   pCommander = pNew;
349 }
350 
351 
352 /**********************************************************************
353  * DEBUG_WIN::DEBUG_WIN
354  *
355  * Create a debug window with size according to the arguments.
356  * Create an hpterm window with a pipe connected to it.
357  **********************************************************************/
358 
DEBUG_WIN(const char * title,inT32 xpos,inT32 ypos,inT32 xsize,inT32 ysize,inT32 buflines)359 DEBUG_WIN::DEBUG_WIN(                    //constructor
360                      const char *title,  //of window
361                      inT32 xpos,         //initial position
362                      inT32 ypos,         //in pixels
363                      inT32 xsize,        //initial size
364                      inT32 ysize,        //in pixels
365                      inT32 buflines      //default scroll size
366                     ) {
367   inT32 length;                  /*length of name */
368 
369   // don't replace this DebugStr() with a call to DEBUG_WIN!
370 
371   //if (pCommander==NULL) DebugStr("\pDEBUG_WIN::DEBUG_WIN(), Commander not set");
372 
373   // create the window
374 
375   //pWindow=LWindow::CreateWindow(2700,pCommander);
376 }
377 
378 
379 /**********************************************************************
380  * DEBUG_WIN::DEBUG_WIN
381  *
382  * Close the file and destroy the window.
383  **********************************************************************/
384 
~DEBUG_WIN()385 DEBUG_WIN::~DEBUG_WIN (
386 //destructor
387 ) {
388 }
389 
390 
391 /**********************************************************************
392  * dprintf
393  *
394  * Print a message to the debug window.
395  * Like printf, this function can cope with messages which do not end
396  * in newline, but nothing is printed until the newline is received.
397  **********************************************************************/
398 
399 void
dprintf(const char * format,...)400 DEBUG_WIN::dprintf (             //debug printf
401 const char *format, ...          //special message
402 ) {
403   #if 0
404   LTextEdit *pTextEdit;
405   va_list args;                  //variable args
406   static char msg[1024];
407 
408   inT32 i;
409   inT32 OriginalLength;
410   inT32 NewLength;
411   TEHandle hTextEdit;
412   char *pTempBuffer;
413   CharsHandle hChar;
414   char *pOriginalText;
415   inT32 StringLength;
416 
417   pTextEdit = (LTextEdit *) pWindow->FindPaneByID (text_FLOWED);
418   if (pTextEdit == NULL)
419     DebugStr ("\pwhoops");
420 
421   // get a C String from the format and args passed in
422 
423   va_start(args, format);  //variable list
424   vsprintf(msg, format, args);  //Format into msg
425   va_end(args);
426 
427   StringLength = strlen (msg);
428 
429   // get the handle for the text
430 
431   hTextEdit = pTextEdit->GetMacTEH ();
432   if (hTextEdit == NULL)
433     DebugStr ("\pDEBUG_WIN,WriteCharsToConsole()");
434 
435   // get a pointer to the characters and the length of the character stream
436 
437   hChar = TEGetText (hTextEdit);
438   if (hChar == NULL)
439     DebugStr ("\pDEBUG_WIN,WriteCharsToConsole()");
440 
441   pOriginalText = *hChar;        // get pointer to existing text
442 
443                                  // get the length of the original data
444   OriginalLength = (*hTextEdit)->teLength;
445 
446   // setup a temporary buffer for the new text
447 
448   NewLength = OriginalLength + StringLength;
449 
450   pTempBuffer = NewPtr (NewLength);
451   if (pTempBuffer == NULL)
452     DebugStr ("\pDEBUG_WIN,WriteCharsToConsole()");
453 
454   // copy the original data into the new buffer
455 
456   for (i = 0; i < OriginalLength; i++)
457     pTempBuffer[i] = pOriginalText[i];
458 
459   // append the new data onto the end of the original buffer
460 
461   for (i = 0; i < StringLength; i++) {
462     if (msg[i] == '\n')
463       pTempBuffer[i + OriginalLength] = '\r';
464     else
465       pTempBuffer[i + OriginalLength] = msg[i];
466   }
467 
468   // put the new text into the text edit item
469 
470   TESetText(pTempBuffer, NewLength, hTextEdit);
471 
472   // clean up
473 
474   DisposePtr(pTempBuffer);
475   #endif
476 }
477 #endif                           //Mac Implmentation
478 
479 #else                            // Non graphical debugger
480 
DEBUG_WIN(const char *,inT32,inT32,inT32,inT32,inT32)481 DEBUG_WIN::DEBUG_WIN( const char*, inT32, inT32, inT32, inT32, inT32 ) {
482 }
483 
~DEBUG_WIN()484 DEBUG_WIN::~DEBUG_WIN () {
485 }
486 
dprintf(const char * format,...)487 void DEBUG_WIN::dprintf (const char *format, ...) {
488   va_list ap;
489   va_start(ap, format);
490   vfprintf(stderr, format, ap);
491   va_end(ap);
492 }
493 
await_destruction()494 void await_destruction() {
495 }
496 
497 
498 #endif
499 
500