Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals  

win_prnt.cc

Go to the documentation of this file.
00001 /*********************************************************************
00002 * File: win_prnt.cc
00003 * Purpose: To make RCS applications that use commands like printf more
00004 * easily ported to Windows and to give windows users the debug and error
00005 * information normally sent to the stdout or stderr.
00006 * The printf calls in the RCS library have been replaced with rcs_print
00007 * and it's cousins in rcs_prnt.cc. For programs that can be run from a
00008 * dos or unix command shell the output is directed to stderr or stdout so
00009 * they work as before. But under Windows the output is directed to a linked
00010 * list called the rcs_print_list. The functions in this file create, update,
00011 * and manipulate a window for viewing that linked list.
00012 ***********************************************************************/
00013 #include <windows.h>
00014 #pragma hdrstop
00015 
00016 #include "rcs_defs.hh"          /* RCS_CALLBACK_FUNC, _Windows */
00017 
00018 #ifdef _Windows
00019 
00020 #include <windows.h>            /* almost everything */
00021 #include <stdlib.h>             // abs()
00022 #include <string.h>             /* strlen() */
00023 #include "win_prnt.hh"
00024 #include "rcs_prnt.hh"          /* get_rcs_print_list(), */
00025                                 /* set_rcs_print_notify(), */
00026                                 /* get_rcs_lines_table() */
00027 
00028 
00029 void (*callback_on_rcs_print_window_close) (void) = NULL;
00030 
00031 #ifdef UNDER_CE
00032 #include "rcs_ce.h"             // RCS_CE_ASCII_TO_UNICODE
00033 #endif
00034 
00035 
00036 #if _MSC_VER >= 1200
00037 extern long RCS_FAR RCS_WINPROC_TYPE rcs_window_proc (HWND _hwnd,
00038                                                       UINT _message,
00039                                                       UINT _wParam,
00040                                                       LONG _lParam);
00041 #else
00042 extern long RCS_FAR RCS_WINPROC_TYPE rcs_window_proc (void RCS_FAR * _hwnd,
00043                                                       unsinged int _message,
00044                                                       unsigned int _wParam,
00045                                                       LONG _lParam);
00046 #endif
00047 
00048 
00049 void RCS_FAR RCS_PASCAL update_rcs_print_window ();
00050 
00051 /* Private Global Data */
00052 WNDCLASS wndclass;
00053 void RCS_FAR *hwnd = NULL;
00054 void RCS_FAR *hwndParent = NULL;
00055 void RCS_FAR *hInstance = NULL;
00056 short char_width = 10;
00057 short char_height = 10;
00058 int x = 0;
00059 int y = 0;
00060 int max_line_width = 0;
00061 int client_height = 0;
00062 int client_width = 0;
00063 int number_of_lines_in_memory = 0;
00064 int number_of_lines_on_screen = 0;
00065 int current_line = 0;
00066 int current_collumn = 0;
00067 int number_of_collumns_on_screen = 0;
00068 RECT client_rect;
00069 
00070 /********************************************************************
00071 * Function: update_rcs_print_window()
00072 * Purpose: Forces the ouput window (if it has been created) to update
00073 * its display. Use set_rcs_print_notify so that it will be called
00074 * whenever there`s an rcs_print.
00075 ********************************************************************/
00076 void RCS_FAR RCS_PASCAL
00077 update_rcs_print_window ()
00078 {
00079   RECT invalid_rect;
00080   update_lines_table ();
00081   number_of_lines_in_memory = get_rcs_print_list_size ();
00082   if (hwnd != NULL)             /* Check to see if window has been created. */
00083     {
00084 
00085       /* If the display region hasn't been filled yet we don't have to */
00086       /* scroll the screen. */
00087       if (number_of_lines_in_memory - current_line <
00088           number_of_lines_on_screen)
00089         {
00090           invalid_rect.top = current_line * char_height;
00091           invalid_rect.left = 0;
00092           invalid_rect.bottom = number_of_lines_in_memory * char_height;
00093           invalid_rect.right = client_width;
00094           InvalidateRect ((HWND) hwnd, &invalid_rect, FALSE);
00095         }
00096       else
00097         {
00098           current_line =
00099             number_of_lines_in_memory - number_of_lines_on_screen;
00100           SetScrollRange ((HWND) hwnd, SB_VERT, 0, current_line, FALSE);
00101           SetScrollPos ((HWND) hwnd, SB_VERT, current_line, TRUE);
00102           invalid_rect.top = 0;
00103           invalid_rect.left = 0;
00104           invalid_rect.bottom = client_height;
00105           invalid_rect.right = client_width;
00106           InvalidateRect ((HWND) hwnd, &invalid_rect, TRUE);
00107         }
00108     }
00109 }
00110 
00111 void RCS_FAR *RCS_EXPORT
00112 create_default_rcs_print_window ()
00113 {
00114   return create_rcs_print_window (NULL, SW_SHOW, NULL);
00115 }
00116 
00117 void RCS_FAR *RCS_EXPORT
00118 create_rcs_print_window (void RCS_FAR * _hInstance, int _nCmdShow,
00119                          void RCS_FAR * _hwndParent)
00120 {
00121   if (hwnd == NULL)
00122     {
00123       hInstance = _hInstance;
00124       hwndParent = _hwndParent;
00125 
00126       wndclass.style = CS_HREDRAW | CS_VREDRAW;
00127       wndclass.lpfnWndProc = rcs_window_proc;
00128       wndclass.cbClsExtra = 0;
00129       wndclass.cbWndExtra = 0;
00130       wndclass.hInstance = (HINSTANCE) hInstance;
00131 #ifndef UNDER_CE
00132       wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
00133       wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
00134 #else
00135       wndclass.hIcon = NULL;
00136       wndclass.hCursor = NULL;
00137 #endif
00138       wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
00139       wndclass.lpszMenuName = NULL;
00140       wndclass.lpszClassName = TEXT ("RCS_OUT");
00141 
00142       if (!RegisterClass (&wndclass))
00143         {
00144           return NULL;
00145         }
00146 
00147       hwnd = CreateWindow (TEXT ("RCS_OUT"),
00148                            TEXT ("RCS_OUT"),
00149                            WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
00150                            WS_VSCROLL | WS_HSCROLL, CW_USEDEFAULT,
00151                            CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
00152                            (HWND) hwndParent, NULL, (HINSTANCE) hInstance,
00153                            NULL);
00154 
00155       if (NULL == hwnd)
00156         {
00157           return NULL;
00158         }
00159 
00160       ShowWindow ((HWND) hwnd, _nCmdShow);
00161       UpdateWindow ((HWND) hwnd);
00162 
00163       set_rcs_print_notify ((RCS_PRINT_NOTIFY_FUNC_PTR)
00164                             update_rcs_print_window);
00165     }
00166   return (hwnd);
00167 }
00168 
00169 void RCS_EXPORT
00170 remove_rcs_print_window ()
00171 {
00172   if (NULL != hwnd)
00173     {
00174       PostMessage ((HWND) hwnd, WM_DESTROY, 0, 0);
00175     }
00176 }
00177 
00178 #if _MSC_VER >= 1200
00179 extern long RCS_FAR RCS_WINPROC_TYPE
00180 rcs_window_proc (HWND _hwnd, UINT _message, UINT _wParam, LONG _lParam)
00181 #else
00182 extern long RCS_FAR RCS_WINPROC_TYPE
00183 rcs_window_proc (void RCS_FAR * _hwnd,
00184                  UINT _message, UINT _wParam, LONG _lParam)
00185 #endif
00186 {
00187   HDC hdc;
00188   TEXTMETRIC tm;
00189   RECT invalid_rect;
00190 
00191   switch (_message)
00192     {
00193     case WM_CREATE:
00194       hdc = GetDC (_hwnd);
00195 
00196       if (NULL == hdc)
00197         {
00198           return (-1);
00199         }
00200       GetTextMetrics (hdc, &tm);
00201       char_width = (short) tm.tmAveCharWidth;
00202       char_height = (short) (tm.tmHeight + tm.tmExternalLeading);
00203       GetClientRect (_hwnd, &client_rect);
00204       client_width = abs (client_rect.right - client_rect.left);
00205       if (client_width < 10)
00206         {
00207           client_width = 10;
00208         }
00209       client_height = abs (client_rect.top - client_rect.bottom);
00210       if (client_height < 10)
00211         {
00212           client_height = 10;
00213         }
00214       number_of_lines_on_screen = client_height / char_height;
00215       if (number_of_lines_on_screen < 5)
00216         {
00217           number_of_lines_on_screen = 5;
00218         }
00219       if (number_of_lines_on_screen > 250)
00220         {
00221           number_of_lines_on_screen = 250;
00222         }
00223       ReleaseDC (_hwnd, hdc);
00224       number_of_lines_in_memory = 0;
00225       max_line_width = 0;
00226       current_line = 0;
00227       current_collumn = 0;
00228       return 0;
00229 
00230     case WM_SIZE:
00231       client_height = HIWORD (_lParam);
00232       client_width = LOWORD (_lParam);
00233       number_of_lines_on_screen = client_height / char_height;
00234       number_of_collumns_on_screen = client_width / char_width;
00235 
00236       if (number_of_lines_in_memory > number_of_lines_on_screen)
00237         {
00238           SetScrollRange (_hwnd, SB_VERT, 0,
00239                           number_of_lines_in_memory -
00240                           number_of_lines_on_screen, FALSE);
00241           SetScrollPos (_hwnd, SB_VERT, current_line, TRUE);
00242         }
00243       else
00244         {
00245           SetScrollRange (_hwnd, SB_VERT, 0, 0, FALSE);
00246           current_line = 0;
00247           SetScrollPos (_hwnd, SB_VERT, 0, TRUE);
00248         }
00249 
00250       if (max_line_width > number_of_collumns_on_screen)
00251         {
00252           SetScrollRange (_hwnd, SB_HORZ, 0,
00253                           max_line_width - number_of_collumns_on_screen,
00254                           FALSE);
00255           SetScrollPos (_hwnd, SB_HORZ, current_collumn, TRUE);
00256         }
00257       else
00258         {
00259           SetScrollRange (_hwnd, SB_HORZ, 0, 0, FALSE);
00260           current_collumn = 0;
00261           SetScrollPos (_hwnd, SB_HORZ, 0, TRUE);
00262         }
00263       invalid_rect.top = 0;
00264       invalid_rect.left = 0;
00265       invalid_rect.bottom = client_height;
00266       invalid_rect.right = client_width;
00267       InvalidateRect (_hwnd, &invalid_rect, TRUE);
00268       return 0;
00269 
00270     case WM_VSCROLL:
00271       switch (_wParam)
00272         {
00273         case SB_TOP:
00274           current_line = 0;
00275           break;
00276 
00277         case SB_BOTTOM:
00278           current_line =
00279             number_of_lines_in_memory - number_of_lines_on_screen;
00280           break;
00281 
00282         case SB_LINEUP:
00283           if (current_line > 0)
00284             {
00285               current_line--;
00286             }
00287           break;
00288 
00289         case SB_LINEDOWN:
00290           if (current_line <
00291               number_of_lines_in_memory - number_of_lines_on_screen)
00292             {
00293               current_line++;
00294             }
00295           break;
00296 
00297         case SB_PAGEUP:
00298           if (current_line > number_of_lines_on_screen)
00299             {
00300               current_line -= number_of_lines_on_screen;
00301             }
00302           else
00303             {
00304               current_line = 0;
00305             }
00306           break;
00307 
00308         case SB_PAGEDOWN:
00309           if (current_line <
00310               number_of_lines_in_memory - 2 * number_of_lines_on_screen)
00311             {
00312               current_line += number_of_lines_on_screen;
00313             }
00314           else
00315             {
00316               current_line =
00317                 number_of_lines_in_memory - number_of_lines_on_screen;
00318             }
00319           break;
00320 
00321         case SB_THUMBTRACK:
00322           int track_pos;
00323           track_pos = LOWORD (_lParam);
00324           if ((track_pos > 0) &&
00325               (track_pos <
00326                number_of_lines_in_memory - number_of_lines_on_screen))
00327             {
00328               current_line = track_pos;
00329             }
00330           break;
00331 
00332         default:
00333           break;
00334         }
00335       SetScrollPos (_hwnd, SB_VERT, current_line, TRUE);
00336       invalid_rect.top = 0;
00337       invalid_rect.left = 0;
00338       invalid_rect.bottom = client_height;
00339       invalid_rect.right = client_width;
00340       InvalidateRect (_hwnd, &invalid_rect, TRUE);
00341       return 0;
00342 
00343     case WM_HSCROLL:
00344       switch (_wParam)
00345         {
00346         case SB_TOP:
00347           current_collumn = 0;
00348           break;
00349 
00350         case SB_BOTTOM:
00351           current_collumn = max_line_width - number_of_collumns_on_screen;
00352           break;
00353 
00354         case SB_LINEUP:
00355           if (current_collumn > 0)
00356             {
00357               current_collumn--;
00358             }
00359           break;
00360 
00361         case SB_LINEDOWN:
00362           if (current_collumn < max_line_width - number_of_collumns_on_screen)
00363             {
00364               current_collumn++;
00365             }
00366           break;
00367 
00368         case SB_PAGEUP:
00369           if (current_collumn > number_of_collumns_on_screen)
00370             {
00371               current_collumn -= number_of_collumns_on_screen;
00372             }
00373           else
00374             {
00375               current_collumn = 0;
00376             }
00377           break;
00378 
00379         case SB_PAGEDOWN:
00380           if (current_collumn <
00381               max_line_width - 2 * number_of_collumns_on_screen)
00382             {
00383               current_collumn += number_of_collumns_on_screen;
00384             }
00385           else
00386             {
00387               current_collumn = max_line_width - number_of_collumns_on_screen;
00388             }
00389           break;
00390 
00391         case SB_THUMBTRACK:
00392           int thumb_pos;
00393           thumb_pos = LOWORD (_lParam);
00394           if ((thumb_pos > 0) &&
00395               (thumb_pos < max_line_width - number_of_collumns_on_screen))
00396             {
00397               current_collumn = thumb_pos;
00398             }
00399           break;
00400 
00401         default:
00402           break;
00403         }
00404       SetScrollPos (_hwnd, SB_HORZ, current_collumn, TRUE);
00405       invalid_rect.top = 0;
00406       invalid_rect.left = 0;
00407       invalid_rect.bottom = client_height;
00408       invalid_rect.right = client_width;
00409       InvalidateRect (_hwnd, &invalid_rect, TRUE);
00410       return 0;
00411 
00412 
00413     case WM_PAINT:
00414       PAINTSTRUCT ps;
00415       int line_width;
00416       hdc = BeginPaint (_hwnd, &ps);
00417       x = (10 + char_width) - current_collumn * char_width;
00418       int max_line_width_changed;
00419       max_line_width_changed = 0;
00420       if (NULL != get_rcs_print_list ())
00421         {
00422           if (NULL != get_rcs_lines_table ())
00423             {
00424               for (int i = current_line; (i < number_of_lines_in_memory) &&
00425                    (i < current_line + number_of_lines_on_screen); i++)
00426                 {
00427                   y = (i - current_line) * char_height;
00428                   char RCS_FAR *cleaned_line;
00429                   cleaned_line = strip_control_characters (NULL,
00430                                                            get_rcs_lines_table
00431                                                            ()[i]);
00432                   if (NULL != cleaned_line)
00433                     {
00434                       line_width = strlen (cleaned_line);
00435                       if (line_width > max_line_width)
00436                         {
00437                           max_line_width = line_width;
00438                           max_line_width_changed = 1;
00439                         }
00440                       line_width =
00441                         line_width <
00442                         (client_width +
00443                          current_collumn) ? line_width : client_width +
00444                         current_collumn;
00445                       int temp_retval = 0;
00446 #ifndef UNDER_CE
00447                       temp_retval =
00448                         TextOut (hdc, x, y, cleaned_line, line_width);
00449 #else
00450                       RECT r;
00451                       wchar_t wbuf[100];
00452                       r.left = x;
00453                       r.right = y + line_width * 10;
00454                       r.top = y;
00455                       r.bottom = y + 20;
00456                       int clipped_line_width;
00457                       if (line_width > 100)
00458                         {
00459                           clipped_line_width = 100;
00460                         }
00461                       else
00462                         {
00463                           clipped_line_width = line_width;
00464                         }
00465                       if (clipped_line_width > 0)
00466                         {
00467                           RCS_CE_ASCII_TO_UNICODE (wbuf, cleaned_line,
00468                                                    clipped_line_width);
00469                           temp_retval =
00470                             DrawText (hdc, wbuf, clipped_line_width, &r,
00471                                       DT_CALCRECT | DT_SINGLELINE);
00472                           if (temp_retval <= 0)
00473                             {
00474                               temp_retval = GetLastError ();
00475                               OutputDebugString (wbuf);
00476                             }
00477                         }
00478 #endif
00479                     }
00480                 }
00481             }
00482         }
00483       EndPaint (_hwnd, &ps);
00484       if (max_line_width_changed)
00485         {
00486           SetScrollRange (_hwnd, SB_HORZ, 0,
00487                           max_line_width - number_of_collumns_on_screen,
00488                           TRUE);
00489         }
00490       return (0);
00491 
00492     case WM_DESTROY:
00493       if (NULL == hwndParent)
00494         {
00495           PostQuitMessage (0);
00496         }
00497       if (NULL != callback_on_rcs_print_window_close)
00498         {
00499           (*callback_on_rcs_print_window_close) ();
00500         }
00501       hwnd = NULL;
00502       return (0);
00503     }
00504 
00505   return (DefWindowProc (_hwnd, _message, _wParam, _lParam));
00506 }
00507 
00508 
00509 unsigned long RCS_EXPORT
00510 run_rcs_print_window (void *param)
00511 {
00512   MSG msg;
00513   void RCS_FAR *hwnd;
00514   hwnd = create_default_rcs_print_window ();
00515 
00516   while (GetMessage (&msg, (HWND) hwnd, 0, 0) && NULL != hwnd)
00517     {
00518       TranslateMessage (&msg);
00519       DispatchMessage (&msg);
00520     }
00521   if (NULL != callback_on_rcs_print_window_close)
00522     {
00523       (*callback_on_rcs_print_window_close) ();
00524     }
00525   ExitThread (0);
00526   return 0;
00527 }
00528 
00529 DWORD rcs_print_window_thread_id = 0;
00530 HANDLE rcs_print_window_thread_handle = NULL;
00531 void RCS_EXPORT
00532 start_rcs_print_window (void *param)
00533 {
00534   set_rcs_print_notify ((RCS_PRINT_NOTIFY_FUNC_PTR) update_rcs_print_window);
00535   rcs_print_window_thread_handle = CreateThread (NULL,  //LPSECURITY_ATTRIBUTES lpThreadAttributes, pointer to thread security attributes
00536                                                  16384, // DWORD dwStackSize, initial thread stack size, in bytes
00537                                                  (LPTHREAD_START_ROUTINE) run_rcs_print_window, // LPTHREAD_START_ROUTINE lpStartAddress,  pointer to thread function
00538                                                  param, // LPVOID lpParameter, argument for new thread
00539                                                  0,     //DWORD dwCreationFlags,  creation flags
00540                                                  &rcs_print_window_thread_id    // LPDWORD lpThreadId      // pointer to returned thread identifier
00541     );
00542   int tries = 0;
00543   while (NULL == hwnd && tries < 30)
00544     {
00545       Sleep (30);
00546       tries++;
00547     }
00548   return;
00549 }
00550 
00551 
00552 
00553 #endif

Generated on Sun Dec 2 15:56:53 2001 for rcslib by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001