/* Copyright (C) 1996-2001 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under license and may not be copied, modified or distributed except as expressly authorized under the terms of the license contained in the file LICENSE in this distribution. For more information about licensing, please refer to http://www.ghostscript.com/licensing/. For information on commercial licensing, go to http://www.artifex.com/licensing/ or contact Artifex Software, Inc., 101 Lucas Valley Road #110, San Rafael, CA 94903, U.S.A., +1(415)492-9861.*/ /* $Id: dwtext.c,v 1.9 2005/03/04 10:27:39 ghostgum Exp $ */ /* Microsoft Windows text window for Ghostscript. #include <stdlib.h>#include <string.h> /* use only far items */#include <ctype.h> #define STRICT#include <windows.h>#include <windowsx.h>#include <commdlg.h>#include <shellapi.h> #include "dwtext.h" /* Define min and max, but make sure to use the identical definition *//* to the one that all the compilers seem to have.... */#ifndef min# define min(a, b) (((a) < (b)) ? (a) : (b))#endif#ifndef max# define max(a, b) (((a) > (b)) ? (a) : (b))#endif #ifndef EOF#define EOF (-1)#endif /* sysmenu */#define M_COPY_CLIP 1#define M_PASTE_CLIP 2 LRESULT CALLBACK WndTextProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);static void text_error(char *message);static void text_new_line(TW *tw);static void text_update_text(TW *tw, int count);static void text_drag_drop(TW *tw, HDROP hdrop);static void text_copy_to_clipboard(TW *tw);static void text_paste_from_clipboard(TW *tw); static const char* TextWinClassName = "rjlTextWinClass";static const POINT TextWinMinSize = {16, 4}; static voidtext_error(char *message){ MessageBox((HWND)NULL,message,(LPSTR)NULL, MB_ICONHAND | MB_SYSTEMMODAL);} /* Bring Cursor into text window */voidtext_to_cursor(TW *tw){int nXinc=0;int nYinc=0;int cxCursor;int cyCursor; cyCursor = tw->CursorPos.y * tw->CharSize.y; if ( (cyCursor + tw->CharSize.y > tw->ScrollPos.y + tw->ClientSize.y) /* || (cyCursor < tw->ScrollPos.y) ) { *//* change to scroll to end of window instead of just making visible *//* so that ALL of error message can be seen */ || (cyCursor < tw->ScrollPos.y+tw->ClientSize.y) ) { nYinc = max(0, cyCursor + tw->CharSize.y - tw->ClientSize.y) - tw->ScrollPos.y; nYinc = min(nYinc, tw->ScrollMax.y - tw->ScrollPos.y); } cxCursor = tw->CursorPos.x * tw->CharSize.x; if ( (cxCursor + tw->CharSize.x > tw->ScrollPos.x + tw->ClientSize.x) || (cxCursor < tw->ScrollPos.x) ) { nXinc = max(0, cxCursor + tw->CharSize.x - tw->ClientSize.x/2) - tw->ScrollPos.x; nXinc = min(nXinc, tw->ScrollMax.x - tw->ScrollPos.x); } if (nYinc || nXinc) { tw->ScrollPos.y += nYinc; tw->ScrollPos.x += nXinc; ScrollWindow(tw->hwnd,-nXinc,-nYinc,NULL,NULL); SetScrollPos(tw->hwnd,SB_VERT,tw->ScrollPos.y,TRUE); SetScrollPos(tw->hwnd,SB_HORZ,tw->ScrollPos.x,TRUE); UpdateWindow(tw->hwnd); }} static voidtext_new_line(TW *tw){ tw->CursorPos.x = 0; tw->CursorPos.y++; if (tw->CursorPos.y >= tw->ScreenSize.y) { int i = tw->ScreenSize.x * (tw->ScreenSize.y - 1); memmove(tw->ScreenBuffer, tw->ScreenBuffer+tw->ScreenSize.x, i); memset(tw->ScreenBuffer + i, ' ', tw->ScreenSize.x); tw->CursorPos.y--; ScrollWindow(tw->hwnd,0,-tw->CharSize.y,NULL,NULL); UpdateWindow(tw->hwnd); } if (tw->CursorFlag) text_to_cursor(tw); /* TextMessage(); */} /* Update count characters in window at cursor position *//* Updates cursor position */static voidtext_update_text(TW *tw, int count){HDC hdc;int xpos, ypos; xpos = tw->CursorPos.x*tw->CharSize.x - tw->ScrollPos.x; ypos = tw->CursorPos.y*tw->CharSize.y - tw->ScrollPos.y; hdc = GetDC(tw->hwnd); SelectFont(hdc, tw->hfont); TextOut(hdc,xpos,ypos, (LPSTR)(tw->ScreenBuffer + tw->CursorPos.y*tw->ScreenSize.x + tw->CursorPos.x), count); (void)ReleaseDC(tw->hwnd,hdc); tw->CursorPos.x += count; if (tw->CursorPos.x >= tw->ScreenSize.x) text_new_line(tw);} voidtext_size(TW *tw, int width, int height){ tw->ScreenSize.x = max(width, TextWinMinSize.x); tw->ScreenSize.y = max(height, TextWinMinSize.y);} voidtext_font(TW *tw, const char *name, int size){ /* make a new font */ LOGFONT lf; TEXTMETRIC tm; LPSTR p; HDC hdc; /* reject inappropriate arguments */ if (name == NULL) return; if (size < 4) return; /* set new name and size */ if (tw->fontname) free(tw->fontname); tw->fontname = (char *)malloc(strlen(name)+1); if (tw->fontname == NULL) return; strcpy(tw->fontname, name); tw->fontsize = size; /* if window not open, hwnd == 0 == HWND_DESKTOP */ hdc = GetDC(tw->hwnd); memset(&lf, 0, sizeof(LOGFONT)); strncpy(lf.lfFaceName,tw->fontname,LF_FACESIZE); lf.lfHeight = -MulDiv(tw->fontsize, GetDeviceCaps(hdc, LOGPIXELSY), 72); lf.lfPitchAndFamily = FIXED_PITCH; lf.lfCharSet = DEFAULT_CHARSET; if ( (p = strstr(tw->fontname," Italic")) != (LPSTR)NULL ) { lf.lfFaceName[ (unsigned int)(p-tw->fontname) ] = '\0'; lf.lfItalic = TRUE; } if ( (p = strstr(tw->fontname," Bold")) != (LPSTR)NULL ) { lf.lfFaceName[ (unsigned int)(p-tw->fontname) ] = '\0'; lf.lfWeight = FW_BOLD; } if (tw->hfont) DeleteFont(tw->hfont); tw->hfont = CreateFontIndirect((LOGFONT FAR *)&lf); /* get text size */ SelectFont(hdc, tw->hfont); GetTextMetrics(hdc,(TEXTMETRIC FAR *)&tm); tw->CharSize.y = tm.tmHeight; tw->CharSize.x = tm.tmAveCharWidth; tw->CharAscent = tm.tmAscent; if (tw->bFocus) CreateCaret(tw->hwnd, 0, tw->CharSize.x, 2+tw->CaretHeight); ReleaseDC(tw->hwnd, hdc); /* redraw window if necessary */ if (tw->hwnd != HWND_DESKTOP) { /* INCOMPLETE */ }} /* Set drag strings */voidtext_drag(TW *tw, const char *pre, const char *post){ /* remove old strings */ if (tw->DragPre) free((char *)tw->DragPre); tw->DragPre = NULL; if (tw->DragPost) free((char *)tw->DragPost); tw->DragPost = NULL; /* add new strings */ tw->DragPre = malloc(strlen(pre)+1); if (tw->DragPre) strcpy(tw->DragPre, pre); tw->DragPost = malloc(strlen(post)+1); if (tw->DragPost) strcpy(tw->DragPost, post);} /* Set the window position and size */void text_setpos(TW *tw, int x, int y, int cx, int cy){ tw->x = x; tw->y = y; tw->cx = cx; tw->cy = cy;} /* Get the window position and size */int text_getpos(TW *tw, int *px, int *py, int *pcx, int *pcy){ *px = tw->x; *py = tw->y; *pcx = tw->cx; *pcy = tw->cy; return 0;} /* Allocate new text window */TW *text_new(void){ TW *tw; tw = (TW *)malloc(sizeof(TW)); if (tw == NULL) return NULL; /* make sure everything is null */ memset(tw, 0, sizeof(TW)); /* set some defaults */ text_font(tw, "Courier New", 10); text_size(tw, 80, 24); tw->KeyBufSize = 2048; tw->CursorFlag = 1; /* scroll to cursor after \n or \r */ tw->hwnd = HWND_DESKTOP; tw->line_end = 0; tw->line_start = 0; tw->line_complete = FALSE; tw->line_eof = FALSE; tw->x = CW_USEDEFAULT; tw->y = CW_USEDEFAULT; tw->cx = CW_USEDEFAULT; tw->cy = CW_USEDEFAULT; return tw;} /* Destroy window and deallocate text window structure */voidtext_destroy(TW *tw){ if (tw->hwnd) DestroyWindow(tw->hwnd); tw->hwnd = HWND_DESKTOP; if (tw->hfont) DeleteFont(tw->hfont); tw->hfont = NULL; if (tw->KeyBuf) free((char *)tw->KeyBuf); tw->KeyBuf = NULL; if (tw->ScreenBuffer) free((char *)tw->ScreenBuffer); tw->ScreenBuffer = NULL; if (tw->DragPre) free((char *)tw->DragPre); tw->DragPre = NULL; if (tw->DragPost) free((char *)tw->DragPost); tw->DragPost = NULL; if (tw->fontname) free((char *)tw->fontname); tw->fontname = NULL;} /* register the window class */inttext_register_class(TW *tw, HICON hicon){ WNDCLASS wndclass; HINSTANCE hInstance = GetModuleHandle(NULL); tw->hIcon = hicon; /* register window class */ wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndTextProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = sizeof(void *); wndclass.hInstance = hInstance; wndclass.hIcon = tw->hIcon ? tw->hIcon : LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = GetStockBrush(WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = TextWinClassName; return RegisterClass(&wndclass);} /* Show the window */inttext_create(TW *tw, const char *app_name, int show_cmd){ HMENU sysmenu; HINSTANCE hInstance = GetModuleHandle(NULL); tw->Title = app_name; tw->nCmdShow = show_cmd; tw->quitnow = FALSE; /* make sure we have some sensible defaults */ if (tw->KeyBufSize < 256) tw->KeyBufSize = 256; tw->CursorPos.x = tw->CursorPos.y = 0; tw->bFocus = FALSE; tw->bGetCh = FALSE; tw->CaretHeight = 0; /* allocate buffers */ tw->KeyBufIn = tw->KeyBufOut = tw->KeyBuf = malloc(tw->KeyBufSize); if (tw->KeyBuf == NULL) { text_error("Out of memory"); return 1; } tw->ScreenBuffer = malloc(tw->ScreenSize.x * tw->ScreenSize.y); if (tw->ScreenBuffer == NULL) { text_error("Out of memory"); return 1; } memset(tw->ScreenBuffer, ' ', tw->ScreenSize.x * tw->ScreenSize.y); tw->hwnd = CreateWindow(TextWinClassName, tw->Title, WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL, tw->x, tw->y, tw->cx, tw->cy, NULL, NULL, hInstance, tw); if (tw->hwnd == NULL) { MessageBox((HWND)NULL,"Couldn't open text window",(LPSTR)NULL, MB_ICONHAND | MB_SYSTEMMODAL); return 1; } ShowWindow(tw->hwnd, tw->nCmdShow); sysmenu = GetSystemMenu(tw->hwnd,0); /* get the sysmenu */ AppendMenu(sysmenu, MF_SEPARATOR, 0, NULL); AppendMenu(sysmenu, MF_STRING, M_COPY_CLIP, "Copy to Clip&board"); AppendMenu(sysmenu, MF_STRING, M_PASTE_CLIP, "&Paste"); return 0;} inttext_putch(TW *tw, int ch){int pos;int n; if (tw->quitnow) return ch; /* don't write error message as we shut down */ switch(ch) { case '\r': tw->CursorPos.x = 0; if (tw->CursorFlag) text_to_cursor(tw); break; case '\n': text_new_line(tw); break; case 7: MessageBeep(-1); if (tw->CursorFlag) text_to_cursor(tw); break; case '\t': { for (n = 8 - (tw->CursorPos.x % 8); n>0; n-- ) text_putch(tw, ' '); } break; case 0x08: case 0x7f: tw->CursorPos.x--; if (tw->CursorPos.x < 0) { tw->CursorPos.x = tw->ScreenSize.x - 1; tw->CursorPos.y--; } if (tw->CursorPos.y < 0) tw->CursorPos.y = 0; break; default: pos = tw->CursorPos.y*tw->ScreenSize.x + tw->CursorPos.x; tw->ScreenBuffer[pos] = ch; text_update_text(tw, 1); } return ch;} void text_write_buf(TW *tw, const char *str, int cnt){BYTE *p;int count, limit;int n; if (tw->quitnow) return; /* don't write error message as we shut down */ while (cnt>0) { p = tw->ScreenBuffer + tw->CursorPos.y*tw->ScreenSize.x + tw->CursorPos.x; limit = tw->ScreenSize.x - tw->CursorPos.x; for (count=0; (count < limit) && (cnt>0) && (isprint((unsigned char)(*str)) || *str=='\t'); count++) { if (*str=='\t') { for (n = 8 - ((tw->CursorPos.x+count) % 8); (count < limit) & (n>0); n--, count++ ) *p++ = ' '; str++; count--; } else { *p++ = *str++; } cnt--; } if (count>0) { text_update_text(tw, count); } if (cnt > 0) { if (*str=='\n') { text_new_line(tw); str++; cnt--; } else if (!isprint((unsigned char)(*str)) && *str!='\t') { text_putch(tw, *str++); cnt--; } } }} /* Put string to window */voidtext_puts(TW *tw, const char *str){ text_write_buf(tw, str, strlen(str));} /* TRUE if key hit, FALSE if no key */inttext_kbhit(TW *tw){ return (tw->KeyBufIn != tw->KeyBufOut);} /* get character from keyboard, no echo *//* need to add extended codes */inttext_getch(TW *tw){ MSG msg; int ch;Lines 1–500 of 1085. Load more
/* Copyright (C) 1996-2001 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under license and may not be copied, modified or distributed except as expressly authorized under the terms of the license contained in the file LICENSE in this distribution. For more information about licensing, please refer to http://www.ghostscript.com/licensing/. For information on commercial licensing, go to http://www.artifex.com/licensing/ or contact Artifex Software, Inc., 101 Lucas Valley Road #110, San Rafael, CA 94903, U.S.A., +1(415)492-9861. */ /* $Id: dwtext.c,v 1.9 2005/03/04 10:27:39 ghostgum Exp $ */ /* Microsoft Windows text window for Ghostscript. #include <stdlib.h> #include <string.h> /* use only far items */ #include <ctype.h> #define STRICT #include <windows.h> #include <windowsx.h> #include <commdlg.h> #include <shellapi.h> #include "dwtext.h" /* Define min and max, but make sure to use the identical definition */ /* to the one that all the compilers seem to have.... */ #ifndef min # define min(a, b) (((a) < (b)) ? (a) : (b)) #endif #ifndef max # define max(a, b) (((a) > (b)) ? (a) : (b)) #endif #ifndef EOF #define EOF (-1) #endif /* sysmenu */ #define M_COPY_CLIP 1 #define M_PASTE_CLIP 2 LRESULT CALLBACK WndTextProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); static void text_error(char *message); static void text_new_line(TW *tw); static void text_update_text(TW *tw, int count); static void text_drag_drop(TW *tw, HDROP hdrop); static void text_copy_to_clipboard(TW *tw); static void text_paste_from_clipboard(TW *tw); static const char* TextWinClassName = "rjlTextWinClass"; static const POINT TextWinMinSize = {16, 4}; static void text_error(char *message) { MessageBox((HWND)NULL,message,(LPSTR)NULL, MB_ICONHAND | MB_SYSTEMMODAL); } /* Bring Cursor into text window */ void text_to_cursor(TW *tw) { int nXinc=0; int nYinc=0; int cxCursor; int cyCursor; cyCursor = tw->CursorPos.y * tw->CharSize.y; if ( (cyCursor + tw->CharSize.y > tw->ScrollPos.y + tw->ClientSize.y) /* || (cyCursor < tw->ScrollPos.y) ) { */ /* change to scroll to end of window instead of just making visible */ /* so that ALL of error message can be seen */ || (cyCursor < tw->ScrollPos.y+tw->ClientSize.y) ) { nYinc = max(0, cyCursor + tw->CharSize.y - tw->ClientSize.y) - tw->ScrollPos.y; nYinc = min(nYinc, tw->ScrollMax.y - tw->ScrollPos.y); } cxCursor = tw->CursorPos.x * tw->CharSize.x; if ( (cxCursor + tw->CharSize.x > tw->ScrollPos.x + tw->ClientSize.x) || (cxCursor < tw->ScrollPos.x) ) { nXinc = max(0, cxCursor + tw->CharSize.x - tw->ClientSize.x/2) - tw->ScrollPos.x; nXinc = min(nXinc, tw->ScrollMax.x - tw->ScrollPos.x); } if (nYinc || nXinc) { tw->ScrollPos.y += nYinc; tw->ScrollPos.x += nXinc; ScrollWindow(tw->hwnd,-nXinc,-nYinc,NULL,NULL); SetScrollPos(tw->hwnd,SB_VERT,tw->ScrollPos.y,TRUE); SetScrollPos(tw->hwnd,SB_HORZ,tw->ScrollPos.x,TRUE); UpdateWindow(tw->hwnd); } } static void text_new_line(TW *tw) { tw->CursorPos.x = 0; tw->CursorPos.y++; if (tw->CursorPos.y >= tw->ScreenSize.y) { int i = tw->ScreenSize.x * (tw->ScreenSize.y - 1); memmove(tw->ScreenBuffer, tw->ScreenBuffer+tw->ScreenSize.x, i); memset(tw->ScreenBuffer + i, ' ', tw->ScreenSize.x); tw->CursorPos.y--; ScrollWindow(tw->hwnd,0,-tw->CharSize.y,NULL,NULL); UpdateWindow(tw->hwnd); } if (tw->CursorFlag) text_to_cursor(tw); /* TextMessage(); */ } /* Update count characters in window at cursor position */ /* Updates cursor position */ static void text_update_text(TW *tw, int count) { HDC hdc; int xpos, ypos; xpos = tw->CursorPos.x*tw->CharSize.x - tw->ScrollPos.x; ypos = tw->CursorPos.y*tw->CharSize.y - tw->ScrollPos.y; hdc = GetDC(tw->hwnd); SelectFont(hdc, tw->hfont); TextOut(hdc,xpos,ypos, (LPSTR)(tw->ScreenBuffer + tw->CursorPos.y*tw->ScreenSize.x + tw->CursorPos.x), count); (void)ReleaseDC(tw->hwnd,hdc); tw->CursorPos.x += count; if (tw->CursorPos.x >= tw->ScreenSize.x) text_new_line(tw); } void text_size(TW *tw, int width, int height) { tw->ScreenSize.x = max(width, TextWinMinSize.x); tw->ScreenSize.y = max(height, TextWinMinSize.y); } void text_font(TW *tw, const char *name, int size) { /* make a new font */ LOGFONT lf; TEXTMETRIC tm; LPSTR p; HDC hdc; /* reject inappropriate arguments */ if (name == NULL) return; if (size < 4) return; /* set new name and size */ if (tw->fontname) free(tw->fontname); tw->fontname = (char *)malloc(strlen(name)+1); if (tw->fontname == NULL) return; strcpy(tw->fontname, name); tw->fontsize = size; /* if window not open, hwnd == 0 == HWND_DESKTOP */ hdc = GetDC(tw->hwnd); memset(&lf, 0, sizeof(LOGFONT)); strncpy(lf.lfFaceName,tw->fontname,LF_FACESIZE); lf.lfHeight = -MulDiv(tw->fontsize, GetDeviceCaps(hdc, LOGPIXELSY), 72); lf.lfPitchAndFamily = FIXED_PITCH; lf.lfCharSet = DEFAULT_CHARSET; if ( (p = strstr(tw->fontname," Italic")) != (LPSTR)NULL ) { lf.lfFaceName[ (unsigned int)(p-tw->fontname) ] = '\0'; lf.lfItalic = TRUE; } if ( (p = strstr(tw->fontname," Bold")) != (LPSTR)NULL ) { lf.lfFaceName[ (unsigned int)(p-tw->fontname) ] = '\0'; lf.lfWeight = FW_BOLD; } if (tw->hfont) DeleteFont(tw->hfont); tw->hfont = CreateFontIndirect((LOGFONT FAR *)&lf); /* get text size */ SelectFont(hdc, tw->hfont); GetTextMetrics(hdc,(TEXTMETRIC FAR *)&tm); tw->CharSize.y = tm.tmHeight; tw->CharSize.x = tm.tmAveCharWidth; tw->CharAscent = tm.tmAscent; if (tw->bFocus) CreateCaret(tw->hwnd, 0, tw->CharSize.x, 2+tw->CaretHeight); ReleaseDC(tw->hwnd, hdc); /* redraw window if necessary */ if (tw->hwnd != HWND_DESKTOP) { /* INCOMPLETE */ } } /* Set drag strings */ void text_drag(TW *tw, const char *pre, const char *post) { /* remove old strings */ if (tw->DragPre) free((char *)tw->DragPre); tw->DragPre = NULL; if (tw->DragPost) free((char *)tw->DragPost); tw->DragPost = NULL; /* add new strings */ tw->DragPre = malloc(strlen(pre)+1); if (tw->DragPre) strcpy(tw->DragPre, pre); tw->DragPost = malloc(strlen(post)+1); if (tw->DragPost) strcpy(tw->DragPost, post); } /* Set the window position and size */ void text_setpos(TW *tw, int x, int y, int cx, int cy) { tw->x = x; tw->y = y; tw->cx = cx; tw->cy = cy; } /* Get the window position and size */ int text_getpos(TW *tw, int *px, int *py, int *pcx, int *pcy) { *px = tw->x; *py = tw->y; *pcx = tw->cx; *pcy = tw->cy; return 0; } /* Allocate new text window */ TW * text_new(void) { TW *tw; tw = (TW *)malloc(sizeof(TW)); if (tw == NULL) return NULL; /* make sure everything is null */ memset(tw, 0, sizeof(TW)); /* set some defaults */ text_font(tw, "Courier New", 10); text_size(tw, 80, 24); tw->KeyBufSize = 2048; tw->CursorFlag = 1; /* scroll to cursor after \n or \r */ tw->hwnd = HWND_DESKTOP; tw->line_end = 0; tw->line_start = 0; tw->line_complete = FALSE; tw->line_eof = FALSE; tw->x = CW_USEDEFAULT; tw->y = CW_USEDEFAULT; tw->cx = CW_USEDEFAULT; tw->cy = CW_USEDEFAULT; return tw; } /* Destroy window and deallocate text window structure */ void text_destroy(TW *tw) { if (tw->hwnd) DestroyWindow(tw->hwnd); tw->hwnd = HWND_DESKTOP; if (tw->hfont) DeleteFont(tw->hfont); tw->hfont = NULL; if (tw->KeyBuf) free((char *)tw->KeyBuf); tw->KeyBuf = NULL; if (tw->ScreenBuffer) free((char *)tw->ScreenBuffer); tw->ScreenBuffer = NULL; if (tw->DragPre) free((char *)tw->DragPre); tw->DragPre = NULL; if (tw->DragPost) free((char *)tw->DragPost); tw->DragPost = NULL; if (tw->fontname) free((char *)tw->fontname); tw->fontname = NULL; } /* register the window class */ int text_register_class(TW *tw, HICON hicon) { WNDCLASS wndclass; HINSTANCE hInstance = GetModuleHandle(NULL); tw->hIcon = hicon; /* register window class */ wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndTextProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = sizeof(void *); wndclass.hInstance = hInstance; wndclass.hIcon = tw->hIcon ? tw->hIcon : LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = GetStockBrush(WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = TextWinClassName; return RegisterClass(&wndclass); } /* Show the window */ int text_create(TW *tw, const char *app_name, int show_cmd) { HMENU sysmenu; HINSTANCE hInstance = GetModuleHandle(NULL); tw->Title = app_name; tw->nCmdShow = show_cmd; tw->quitnow = FALSE; /* make sure we have some sensible defaults */ if (tw->KeyBufSize < 256) tw->KeyBufSize = 256; tw->CursorPos.x = tw->CursorPos.y = 0; tw->bFocus = FALSE; tw->bGetCh = FALSE; tw->CaretHeight = 0; /* allocate buffers */ tw->KeyBufIn = tw->KeyBufOut = tw->KeyBuf = malloc(tw->KeyBufSize); if (tw->KeyBuf == NULL) { text_error("Out of memory"); return 1; } tw->ScreenBuffer = malloc(tw->ScreenSize.x * tw->ScreenSize.y); if (tw->ScreenBuffer == NULL) { text_error("Out of memory"); return 1; } memset(tw->ScreenBuffer, ' ', tw->ScreenSize.x * tw->ScreenSize.y); tw->hwnd = CreateWindow(TextWinClassName, tw->Title, WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL, tw->x, tw->y, tw->cx, tw->cy, NULL, NULL, hInstance, tw); if (tw->hwnd == NULL) { MessageBox((HWND)NULL,"Couldn't open text window",(LPSTR)NULL, MB_ICONHAND | MB_SYSTEMMODAL); return 1; } ShowWindow(tw->hwnd, tw->nCmdShow); sysmenu = GetSystemMenu(tw->hwnd,0); /* get the sysmenu */ AppendMenu(sysmenu, MF_SEPARATOR, 0, NULL); AppendMenu(sysmenu, MF_STRING, M_COPY_CLIP, "Copy to Clip&board"); AppendMenu(sysmenu, MF_STRING, M_PASTE_CLIP, "&Paste"); return 0; } int text_putch(TW *tw, int ch) { int pos; int n; if (tw->quitnow) return ch; /* don't write error message as we shut down */ switch(ch) { case '\r': tw->CursorPos.x = 0; if (tw->CursorFlag) text_to_cursor(tw); break; case '\n': text_new_line(tw); break; case 7: MessageBeep(-1); if (tw->CursorFlag) text_to_cursor(tw); break; case '\t': { for (n = 8 - (tw->CursorPos.x % 8); n>0; n-- ) text_putch(tw, ' '); } break; case 0x08: case 0x7f: tw->CursorPos.x--; if (tw->CursorPos.x < 0) { tw->CursorPos.x = tw->ScreenSize.x - 1; tw->CursorPos.y--; } if (tw->CursorPos.y < 0) tw->CursorPos.y = 0; break; default: pos = tw->CursorPos.y*tw->ScreenSize.x + tw->CursorPos.x; tw->ScreenBuffer[pos] = ch; text_update_text(tw, 1); } return ch; } void text_write_buf(TW *tw, const char *str, int cnt) { BYTE *p; int count, limit; int n; if (tw->quitnow) return; /* don't write error message as we shut down */ while (cnt>0) { p = tw->ScreenBuffer + tw->CursorPos.y*tw->ScreenSize.x + tw->CursorPos.x; limit = tw->ScreenSize.x - tw->CursorPos.x; for (count=0; (count < limit) && (cnt>0) && (isprint((unsigned char)(*str)) || *str=='\t'); count++) { if (*str=='\t') { for (n = 8 - ((tw->CursorPos.x+count) % 8); (count < limit) & (n>0); n--, count++ ) *p++ = ' '; str++; count--; } else { *p++ = *str++; } cnt--; } if (count>0) { text_update_text(tw, count); } if (cnt > 0) { if (*str=='\n') { text_new_line(tw); str++; cnt--; } else if (!isprint((unsigned char)(*str)) && *str!='\t') { text_putch(tw, *str++); cnt--; } } } } /* Put string to window */ void text_puts(TW *tw, const char *str) { text_write_buf(tw, str, strlen(str)); } /* TRUE if key hit, FALSE if no key */ int text_kbhit(TW *tw) { return (tw->KeyBufIn != tw->KeyBufOut); } /* get character from keyboard, no echo */ /* need to add extended codes */ int text_getch(TW *tw) { MSG msg; int ch;