?? logwin.c
字號:
// $Id: logwin.c,v 1.7 2000/11/17 07:02:01 ymwei Exp $//// logwin.c: implementation file of log window.//// Copyright (c) 2000, WEI Yongming// Copyright (C) 2000, BluePoint Software.//// Current maintainer: WEI Yongming.//// Create date: 2000.xx.xx/*** This library is free software; you can redistribute it and/or** modify it under the terms of the GNU Library General Public** License as published by the Free Software Foundation; either** version 2 of the License, or (at your option) any later version.**** This library is distributed in the hope that it will be useful,** but WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU** Library General Public License for more details.**** You should have received a copy of the GNU Library General Public** License along with this library; if not, write to the Free** Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,** MA 02111-1307, USA*///// Modify records://// Who When Where For What Status//-----------------------------------------------------------------------------//// TODO://#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <string.h>#include <pthread.h>#include <semaphore.h>#include <sys/stat.h>#include <sys/types.h>#include <unistd.h>#include <errno.h>#include "common.h"#include "minigui.h"#include "gdi.h"#include "window.h"#include "control.h"#include "logwin.h"typedef struct _LogWinCreateInfo{ HWND log_win; sem_t wait; BOOL fVisible; ONCLOSE OnClose; int nr_rows; int nr_cols; int max_lines;} LOGWINCREATEINFO;#define MSG_LW_ADDTEXT (MSG_USER + 1)#define MSG_LW_CLEANUP (MSG_USER + 2)#define MAX_LENGTH_LINE 100typedef struct tagTEXTLINE{ int lineno; char text [MAX_LENGTH_LINE + 1]; struct tagTEXTLINE* next; struct tagTEXTLINE* prev;} TEXTLINE;typedef TEXTLINE* PTEXTLINE;typedef struct _LogWinInfo{ int vis_lines; // number of visible lines in window int max_lines; // maximal number of lines in window int last_line_nr; // number of last line PTEXTLINE lines; // pointer to text PTEXTLINE top_line; // pointer to first visible line} LOGWININFO;typedef LOGWININFO* PLOGWININFO;#define line_count(info) min (info->max_lines, info->last_line_nr)static void logwinSetVScrollInfo (HWND log_win){ PLOGWININFO info; SCROLLINFO si; info = (PLOGWININFO)GetWindowAdditionalData2 (log_win); if (info->vis_lines >= line_count (info)) { SetScrollPos (log_win, SB_VERT, 0); EnableScrollBar (log_win, SB_VERT, FALSE); return; } si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; si.nMax = line_count (info) - 1; si.nMin = 0; si.nPage = min (info->vis_lines, info->last_line_nr - info->top_line->lineno + 1); si.nPos = info->top_line->lineno - info->lines->lineno; SetScrollInfo (log_win, SB_VERT, &si, TRUE); EnableScrollBar (log_win, SB_VERT, TRUE);}static PTEXTLINE next_n_line (PTEXTLINE line, int n){ int i; for (i = 0; i < n && line; i++) { line = line->next; } return line;}static PTEXTLINE prev_n_line (PTEXTLINE line, int n){ int i; for (i = 0; i < n && line; i++) { line = line->prev; } return line;}static void logwinOnVScroll (HWND log_win, int scroll_code, int new_pos){ PTEXTLINE top_line; PLOGWININFO info; int scroll_height = 0; int line_height = GetCharHeight (); int n; info = (PLOGWININFO) GetWindowAdditionalData2 (log_win); top_line = info->top_line; switch (scroll_code) { case SB_LINEDOWN: if ((top_line->lineno + info->vis_lines) <= info->last_line_nr) { top_line = top_line->next; scroll_height = -line_height; } break; case SB_LINEUP: if (top_line->lineno > info->lines->lineno) { top_line = top_line->prev; scroll_height = line_height; } break; case SB_PAGEDOWN: if ((top_line->lineno + (info->vis_lines << 1)) <= info->last_line_nr) n = info->vis_lines; else n = info->last_line_nr - info->vis_lines - top_line->lineno; if (n == 0) return; top_line = next_n_line (top_line, n); scroll_height = -(n * line_height); break; case SB_PAGEUP: n = top_line->lineno - info->lines->lineno; if (n > info->vis_lines) n = info->vis_lines; scroll_height = n * line_height; top_line = prev_n_line (top_line, n); break; case SB_THUMBTRACK: n = new_pos + info->lines->lineno - top_line->lineno; if (n > 0) top_line = next_n_line (top_line, n); else if (n < 0) top_line = prev_n_line (top_line, -n); else return; scroll_height = -(n * line_height); break; } if (scroll_height) { info->top_line = top_line; ScrollWindow (log_win, 0, scroll_height, NULL, NULL); SendMessage (log_win, MSG_PAINT, 0, 0); logwinSetVScrollInfo (log_win); return; }}static BOOL logwinAddTextLine (HWND log_win, const char* text, BOOL fUpdate){ PLOGWININFO info; PTEXTLINE line; PTEXTLINE oldline = NULL; int nCharH = GetCharHeight (); int top_lineno = 1; PTEXTLINE top_next = NULL; info = (PLOGWININFO)GetWindowAdditionalData2 (log_win); if (info->last_line_nr >= info->max_lines) { oldline = info->lines; info->lines = info->lines->next; } if (!info->lines) { if (oldline) info->lines = oldline; else info->lines = malloc (sizeof (TEXTLINE)); if (info->lines == NULL) { info->lines = oldline; return FALSE; } line = info->lines; line->prev = NULL; } else { line = info->lines; while (line->next) { line = line->next; } if (oldline) line->next = oldline; else line->next = malloc (sizeof (TEXTLINE)); if (line->next == NULL) { return FALSE; } line->next->prev = line; line = line->next; } if (info->top_line) { top_lineno = info->top_line->lineno; top_next = info->top_line->next; } strncpy (line->text, text, MAX_LENGTH_LINE); line->text [MAX_LENGTH_LINE] = '\0'; line->next = NULL; line->lineno = ++info->last_line_nr; if (info->last_line_nr == 1) info->top_line = info->lines; if (fUpdate) { RECT rcLine; RECT rcClient; if (info->last_line_nr >= (top_lineno + info->vis_lines)) { info->top_line = top_next; ScrollWindow (log_win, 0, -nCharH, NULL, NULL); SendMessage (log_win, MSG_PAINT, 0, 0); } else { // Get line output rect GetClientRect (log_win, &rcClient); rcLine.left = rcClient.left; rcLine.right = rcClient.right; rcLine.top = rcClient.top + nCharH * (info->last_line_nr - top_lineno); rcLine.bottom = rcLine.top + nCharH; InvalidateRect (log_win, &rcLine, FALSE); SendMessage (log_win, MSG_PAINT, 0, 0); } } logwinSetVScrollInfo (log_win); return TRUE;}static void logwinDeleteContent (HWND log_win){ PLOGWININFO info; PTEXTLINE line; PTEXTLINE next; info = (PLOGWININFO)GetWindowAdditionalData2 (log_win); line = info->lines; if (!line) return; while (line) { next = line->next; free (line); line = next; } info->lines = NULL; info->last_line_nr = 0;}static void logwinOutLogWinText(HWND log_win, HDC hdc){ PLOGWININFO info; PTEXTLINE line; RECT rcClient; RECT rcLine; int iLine = 0; int nCharH = GetCharHeight (); info = (PLOGWININFO)GetWindowAdditionalData2 (log_win); line = info->top_line; GetClientRect (log_win, &rcClient); SetTextColor (hdc, COLOR_lightwhite); SetBkColor (hdc, COLOR_black); while (line) { char szLineNo [10]; rcLine.left = rcClient.left + 2; rcLine.top = rcClient.top + nCharH*iLine; rcLine.right = rcClient.right; rcLine.bottom = rcLine.top + nCharH; sprintf (szLineNo, "%06d", line->lineno); TextOut (hdc, rcLine.left, rcLine.top, szLineNo); TextOut (hdc, rcLine.left + GetCharWidth () * 6 + 4, rcLine.top, line->text); line = line->next; iLine++; }}static int LogWinProc (HWND hWnd, int message, WPARAM wParam, LPARAM lParam){ switch (message) { case MSG_CREATE: EnableScrollBar (hWnd, SB_VERT, FALSE); break; case MSG_PAINT: { HDC hdc; hdc = BeginPaint (hWnd); logwinOutLogWinText(hWnd, hdc); EndPaint (hWnd, hdc); } return 0; case MSG_LW_ADDTEXT: logwinAddTextLine (hWnd, (char*)lParam, TRUE); break; case MSG_LW_CLEANUP: logwinDeleteContent (hWnd); break; case MSG_VSCROLL: logwinOnVScroll (hWnd, (int)wParam, (int)lParam); break; case MSG_CLOSE: { ONCLOSE OnClose = (ONCLOSE) GetWindowAdditionalData (hWnd); if (!OnClose || (*OnClose) (hWnd)) { logwinDeleteContent (hWnd); DestroyMainWindow (hWnd); PostQuitMessage (hWnd); } break; } // case } // switch return DefaultMainWinProc(hWnd, message, wParam, lParam);}static void logwinInitCreateInfo (PMAINWINCREATE pCreateInfo, int rows, int cols){ pCreateInfo->dwStyle = WS_THINFRAME | WS_VSCROLL | WS_CAPTION; pCreateInfo->dwExStyle = WS_EX_NOCLOSEBOX; pCreateInfo->spCaption = "Log Window"; pCreateInfo->hMenu = 0; pCreateInfo->hCursor = GetSystemCursor(0); pCreateInfo->hIcon = 0; pCreateInfo->MainWindowProc = LogWinProc; pCreateInfo->lx = 0; pCreateInfo->ty = GetGDCapability (HDC_SCREEN, GDCAP_MAXY) - GetCharHeight () * rows - 1; pCreateInfo->rx = pCreateInfo->lx + GetCharWidth () * cols + 2; pCreateInfo->rx += GetMainWinMetrics (MWM_CXVSCROLL); pCreateInfo->by = GetGDCapability (HDC_SCREEN, GDCAP_MAXY) + 1; pCreateInfo->ty -= GetMainWinMetrics (MWM_CAPTIONY); pCreateInfo->iBkColor = COLOR_black; pCreateInfo->dwAddData = 0; pCreateInfo->hHosting = HWND_DESKTOP;} static void* LogWindow (void* data){ MSG Msg; MAINWINCREATE CreateInfo; HWND hMainWnd; LOGWINCREATEINFO* LogWinCreateInfo = (LOGWINCREATEINFO*)data; LOGWININFO info; RECT rcClient; if (LogWinCreateInfo->nr_rows <= 0) LogWinCreateInfo->nr_rows = 1; if (LogWinCreateInfo->nr_cols <= 0) LogWinCreateInfo->nr_cols = 1; logwinInitCreateInfo (&CreateInfo, LogWinCreateInfo->nr_rows, LogWinCreateInfo->nr_cols); if (LogWinCreateInfo->fVisible) CreateInfo.dwStyle |= WS_VISIBLE; CreateInfo.dwAddData = (DWORD)(LogWinCreateInfo->OnClose); hMainWnd = CreateMainWindow (&CreateInfo); LogWinCreateInfo->log_win = hMainWnd; info.vis_lines = LogWinCreateInfo->nr_rows; info.max_lines = (LogWinCreateInfo->max_lines > LogWinCreateInfo->nr_rows) ? LogWinCreateInfo->max_lines : LogWinCreateInfo->nr_rows; info.last_line_nr = 0; info.lines = NULL; info.top_line= NULL; sem_post (&LogWinCreateInfo->wait); if (hMainWnd == HWND_INVALID) return NULL; GetClientRect (hMainWnd, &rcClient); SetWindowAdditionalData2 (hMainWnd, (DWORD)(&info)); while( GetMessage (&Msg, hMainWnd) ) { DispatchMessage (&Msg); } MainWindowThreadCleanup (hMainWnd); return NULL;}HWND CreateLogWin (BOOL fVisible, ONCLOSE OnClose, int nr_rows, int nr_cols, int max_lines){ LOGWINCREATEINFO LogWinCreateInfo; pthread_t th; if (nr_rows < 3 || nr_cols < 3) return HWND_INVALID; sem_init (&LogWinCreateInfo.wait, 0, 0); LogWinCreateInfo.fVisible = fVisible; LogWinCreateInfo.OnClose = OnClose; LogWinCreateInfo.nr_rows = nr_rows; LogWinCreateInfo.nr_cols = nr_cols; LogWinCreateInfo.max_lines = max_lines; CreateThreadForMainWindow (&th, NULL, LogWindow, &LogWinCreateInfo); sem_wait (&LogWinCreateInfo.wait); sem_destroy (&LogWinCreateInfo.wait); return LogWinCreateInfo.log_win;} void DestroyLogWin (HWND log_win){ SendMessage (log_win, MSG_CLOSE, 0, 0);}void LogMessage (HWND log_win, const char* format, ...){ char text [MAX_LENGTH_LINE + 1]; va_list args; va_start (args, format); vsnprintf (text, MAX_LENGTH_LINE, format, args); va_end (args); SendMessage (log_win, MSG_LW_ADDTEXT, 0, (LPARAM)text);}int IsLogWinVisible (HWND log_win){ if (log_win == HWND_INVALID) return -1; if (IsWindowVisible (log_win)) return 1; return 0;}void ToggleLogWin (HWND log_win){ switch (IsLogWinVisible (log_win)) { case 0: ShowWindow (log_win, SW_SHOW); break; case 1: ShowWindow (log_win, SW_HIDE); break; }}void DumpAllLogMessages (HWND log_win, FILE* fp){ PLOGWININFO info; PTEXTLINE line; info = (PLOGWININFO)GetWindowAdditionalData2 (log_win); line = info->lines; while (line) { fprintf (fp, "%s\n", line->text); line = line->next; }}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -