From a7e14052086500aab638787c99d9193dcd4a02b9 Mon Sep 17 00:00:00 2001 From: pnenzi Date: Thu, 3 Jan 2002 22:47:29 +0000 Subject: [PATCH] Windows port of Ngspice (Holger Vogt) (part 2) --- src/frontend/wdisp/Makefile.am | 11 + src/frontend/wdisp/ftegraf.h | 16 + src/frontend/wdisp/makedefs | 12 + src/frontend/wdisp/windisp.c | 542 +++++++++++++ src/frontend/wdisp/winprint.c | 451 +++++++++++ src/include/wstdio.h | 97 +++ src/winmain.c | 1323 ++++++++++++++++++++++++++++++++ 7 files changed, 2452 insertions(+) create mode 100644 src/frontend/wdisp/Makefile.am create mode 100644 src/frontend/wdisp/ftegraf.h create mode 100644 src/frontend/wdisp/makedefs create mode 100644 src/frontend/wdisp/windisp.c create mode 100644 src/frontend/wdisp/winprint.c create mode 100644 src/include/wstdio.h create mode 100644 src/winmain.c diff --git a/src/frontend/wdisp/Makefile.am b/src/frontend/wdisp/Makefile.am new file mode 100644 index 000000000..40113c1bc --- /dev/null +++ b/src/frontend/wdisp/Makefile.am @@ -0,0 +1,11 @@ +noinst_LIBRARIES = libwindisp.a + +libwindisp_a_SOURCES = \ + windisp.c \ + winprint.c \ + ftegraf.h + + +INCLUDES = -I$(top_srcdir)/src/include -I$(top_srcdir)/src/frontend/wdisp + +MAINTAINERCLEANFILES = Makefile.in diff --git a/src/frontend/wdisp/ftegraf.h b/src/frontend/wdisp/ftegraf.h new file mode 100644 index 000000000..c25e85439 --- /dev/null +++ b/src/frontend/wdisp/ftegraf.h @@ -0,0 +1,16 @@ +/********** +Copyright 1990 Regents of the University of California. All rights reserved. +Author: 1986 Wayne A. Christopher, U. C. Berkeley CAD Group +**********/ + +/* + * + * Definitions common to the various graphics modules. + */ + +#define G_NONE 0 +#define G_HCOPY 1 +#define G_TERM 2 +#define G_MFB 3 +#define G_X 4 + diff --git a/src/frontend/wdisp/makedefs b/src/frontend/wdisp/makedefs new file mode 100644 index 000000000..d4301ae56 --- /dev/null +++ b/src/frontend/wdisp/makedefs @@ -0,0 +1,12 @@ +########### +# Copyright 2000 Holger Vogt. All rights reserved. +########### + +CFILES = windisp.c winprint.c + +COBJS = windisp.o winprint.o + +LIBRARY = wdisp +LIB_TARGET = $(OBJLIB_DIR)/$(LIBRARY).a +windisp.o: windisp.c +winprint.o: winprint.c diff --git a/src/frontend/wdisp/windisp.c b/src/frontend/wdisp/windisp.c new file mode 100644 index 000000000..3bc23423a --- /dev/null +++ b/src/frontend/wdisp/windisp.c @@ -0,0 +1,542 @@ +/* + * Frame buffer for the IDM PC using MS Windows + * Wolfgang Mües 27.10.97 + * Holger Vogt 07.12.01 + */ + +#define STRICT +#include "ngspice.h" + +#ifdef HAS_WINDOWS + +#include "graph.h" +#include "ftedev.h" +#include "ftedbgra.h" +#pragma warn -dup // wegen Redefinition von NUMCOLORS +#include +#include +#include "suffix.h" +#pragma hdrstop + +// Typen +typedef struct { // Extra Fensterdaten + HWND wnd; // Fenster + HDC hDC; // Device context des Fensters + RECT Area; // Zeichenfläche + int ColorIndex; // Index auf die akt. Farbe + int PaintFlag; // 1 bei WM_PAINT + int FirstFlag; // 1 vor dem ersten Update +} tWindowData; +typedef tWindowData * tpWindowData; // Zeiger darauf +#define pWindowData(g) ((tpWindowData)(g->devdep)) + +// Forwards +LRESULT CALLBACK PlotWindowProc( HWND hwnd, // Fensterprozedur + UINT uMsg, WPARAM wParam, LPARAM lParam); + +// externals +extern HINSTANCE hInst; // Instanz der Applikation +extern int WinLineWidth; // Breite des Textfensters +void WPRINT_PrintInit( HWND hwnd); // Windows Drucker Init +void WaitForIdle(void); // Warte, bis keine Events da + +// lokale Variablen +static int IsRegistered = 0; // 1 wenn Fensterkl. reg. +#define NumWinColors 23 // vordef. Farben +static COLORREF ColorTable[NumWinColors]; // Speicher für die Farben +static char * WindowName = "Spice Plot"; // Fenstername +static WNDCLASS TheWndClass; // Plot-Fensterklasse +static HFONT PlotFont; // Font-Merker +#define ID_DRUCKEN 0xEFF0 // System-Menu: drucken +#define ID_DRUCKEINR 0xEFE0 // System-Menu: Druckereinrichtung +static const int ID_MASK = 0xFFF0; // System-Menu: Maske +static char * STR_DRUCKEN = "Drucken..."; // System-Menu-Strings +static char * STR_DRUCKEINR = "Druckereinrichtung..."; + +/****************************************************************************** +WIN_Init() stellt die Verbindung zur Grafik her. Dazu gehört die Feststellung +von + dispdev->numlinestyles (bei Farbschirmen == 1) + dispdev->numcolors + dispdev->width (vorläufig, Bildschirmbreite) + dispdev->height (vorläufig, Bildschirmhöhe) + +WIN_Init() gibt 0 zurück, falls kein Fehler auftrat. + +WIN_Init() macht noch kein Fenster auf, dies geschieht erst in WIN_NewViewport() +******************************************************************************/ + +int WIN_Init( ) +{ + // Initialisierungen des Display-Descriptors + dispdev->width = GetSystemMetrics( SM_CXSCREEN); + dispdev->height = GetSystemMetrics( SM_CYSCREEN); + dispdev->numlinestyles = 5; // siehe Auswirkungen in WinPrint! + dispdev->numcolors = NumWinColors; + + // nur beim ersten Mal: + if (!IsRegistered) { + + // Farben initialisieren + ColorTable[0] = RGB( 0, 0, 0); // Schwarz = Hintergrund + ColorTable[1] = RGB(255,255,255); // Weiß = Beschriftung und Gitter + ColorTable[2] = RGB( 0,255, 0); // Grün = erste Linie + ColorTable[3] = RGB(255, 0, 0); // Rot + ColorTable[4] = RGB( 0, 0,255); // Blau + ColorTable[5] = RGB(255,255, 0); // Gelb + ColorTable[6] = RGB(255, 0,255); // Violett + ColorTable[7] = RGB( 0,255,255); // Azur + ColorTable[8] = RGB(255,128, 0); // Orange + ColorTable[9] = RGB(128, 64, 0); // braun + ColorTable[10]= RGB(128, 0,255); // Hellviolett + ColorTable[11]= RGB(255,128,128); // Rosa + // 2. Farb-Bank (mit anderem Linientyp + ColorTable[12]= RGB(255,255,255); // Weiß + ColorTable[13]= RGB( 0,255, 0); // Grün + ColorTable[14]= RGB(255, 0, 0); // Rot + ColorTable[15]= RGB( 0, 0,255); // Blau + ColorTable[16]= RGB(255,255, 0); // Gelb + ColorTable[17]= RGB(255, 0,255); // Violett + ColorTable[18]= RGB( 0,255,255); // Azur + ColorTable[19]= RGB(255,128, 0); // Orange + ColorTable[20]= RGB(128, 64, 0); // braun + ColorTable[21]= RGB(128, 0,255); // Hellviolett + ColorTable[22]= RGB(255,128,128); // Rosa + + // Ansii fixed font + PlotFont = GetStockFont( ANSI_FIXED_FONT); + + // Fensterklasse registrieren + TheWndClass.lpszClassName = WindowName; + TheWndClass.hInstance = hInst; + TheWndClass.lpfnWndProc = PlotWindowProc; + TheWndClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; + TheWndClass.lpszMenuName = NULL; + TheWndClass.hCursor = LoadCursor(NULL, IDC_ARROW); + TheWndClass.hbrBackground = GetStockObject( BLACK_BRUSH); + TheWndClass.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(2)); + TheWndClass.cbClsExtra = 0; + TheWndClass.cbWndExtra = sizeof(GRAPH *); + if (!RegisterClass(&TheWndClass)) return 1; + } + IsRegistered = 1; + + // fertig + return (0); +} + +// Zeiger auf den Graphen gewinnen +// (wird an das Fenster angehängt) +static GRAPH * pGraph( HWND hwnd) +{ + return (GRAPH *) GetWindowLong( hwnd, 0); +} + +// Linientyp zurückgeben zum Zeichnen +static int LType( int ColorIndex) +{ + if (ColorIndex >= 12) + return PS_DOT; + else + return PS_SOLID; +} + +// Drucke ein Plotfenster +// Aufruf durch SystemMenü / Drucken +LRESULT PrintPlot( HWND hwnd) +{ + GRAPH * graph; + GRAPH * temp; + + // Zeiger auf die Grafik holen + graph = pGraph( hwnd); + if (!graph) return 0; + + // Umschalten auf den Drucker + // (hat WPRINT_Init() zur Folge) + if (DevSwitch("WinPrint")) return 0; + + // Cursor = warten + SetCursor( LoadCursor( NULL, IDC_WAIT)); + + // Graphen kopieren + temp = CopyGraph(graph); + if (!temp) goto PrintEND; + + // in die Kopie die neuen Daten des Druckers einspeisen + if (NewViewport(temp)) goto PrintEND2; + + // Lage des Gitters korrigieren (Kopie aus gr_init) + temp->viewportxoff = temp->fontwidth * 8; + temp->viewportyoff = temp->fontheight * 4; + + // dies druckt den Graphen + gr_resize(temp); + +PrintEND2: + // temp. Graphen löschen + DestroyGraph(temp->graphid); + +PrintEND: + // zurückschalten auf den Bildschirm + DevSwitch(NULL); + + // Cursor = normal + SetCursor( LoadCursor( NULL, IDC_ARROW)); + + return 0; +} + +// Druckerinitialisierung +LRESULT PrintInit( HWND hwnd) +{ + // weitergeben an das Drucker-Modul + WPRINT_PrintInit(hwnd); + return 0; +} + +// Fensterprozedur +LRESULT CALLBACK PlotWindowProc( HWND hwnd, + UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) { + case WM_SYSCOMMAND: + { + // Kommando testen + int cmd = wParam & ID_MASK; + switch(cmd) { + case ID_DRUCKEN: return PrintPlot( hwnd); + case ID_DRUCKEINR: return PrintInit( hwnd); + } + } + goto WIN_DEFAULT; + + case WM_CLOSE: // Fenster schließen + { + GRAPH * g = pGraph( hwnd); + if (g) + DestroyGraph(g->graphid); + } + goto WIN_DEFAULT; + + case WM_PAINT: // Fenster neuzeichnen (z.B. nach Resize) + { + PAINTSTRUCT ps; + GRAPH * g; + tpWindowData wd; + HDC saveDC; // der DC aus BeginPaint ist anders... + HDC newDC; + + // muss passieren + newDC = BeginPaint( hwnd, &ps); + g = pGraph( hwnd); + if (g) { + wd = pWindowData(g); + if (wd) { + if (!wd->PaintFlag && !wd->FirstFlag) { + // rekursiven Aufruf verhindern + wd->PaintFlag = 1; + // Fenstermaße holen + GetClientRect( hwnd, &(wd->Area)); + g->absolute.width = wd->Area.right; + g->absolute.height = wd->Area.bottom; + // DC umschalten + saveDC = wd->hDC; + wd->hDC = newDC; + // neu zeichnen + gr_resize(g); + // DC umschalten + wd->hDC = saveDC; + // fertig + wd->PaintFlag = 0; + } + } + } + // beenden + EndPaint( hwnd, &ps); + } + return 0; + + default: +WIN_DEFAULT: + return DefWindowProc( hwnd, uMsg, wParam, lParam); + } +} + + +/****************************************************************************** + WIN_NewViewport() erstellt ein neues Fenster mit einem Graphen drin. + + WIN_NewViewport() gibt 0 zurück, falls erfolgreich + +******************************************************************************/ + +int WIN_NewViewport( GRAPH * graph) +{ + int i; + HWND window; + HDC dc; + HDC textDC; + HFONT font; + TEXTMETRIC tm; + tpWindowData wd; + HMENU sysmenu; + + // Parameter testen + if (!graph) return 1; + + // Initialisiere, falls noch nicht geschehen + if (WIN_Init() != 0) { + externalerror("Can't initialize GDI."); + return(1); + } + + // Device dep. Info allocieren + wd = calloc(1, sizeof(tWindowData)); + if (!wd) return 1; + graph->devdep = (char *)wd; + + // Create the window + i = GetSystemMetrics( SM_CYSCREEN) / 3; + window = CreateWindow( WindowName, graph->plotname, WS_OVERLAPPEDWINDOW, + 0, 0, WinLineWidth, i * 2 - 22, NULL, NULL, hInst, NULL); + if (!window) return 1; + wd->wnd = window; + SetWindowLong( window, 0, (long)graph); + + // Zeige das Fenster + ShowWindow( window, SW_SHOWNORMAL); + + // Hole die Maße + GetClientRect( window, &(wd->Area)); + + // Hole den DC + dc = GetDC( window); + wd->hDC = dc; + + // Setze den Color-Index + wd->ColorIndex = 0; + + // noch kein Zeichnen + wd->PaintFlag = 0; + wd->FirstFlag = 1; + + // System-Menu modifizieren + sysmenu = GetSystemMenu( window, FALSE); + AppendMenu( sysmenu, MF_SEPARATOR, 0, NULL); + AppendMenu( sysmenu, MF_STRING, ID_DRUCKEN, STR_DRUCKEN); + AppendMenu( sysmenu, MF_STRING, ID_DRUCKEINR, STR_DRUCKEINR); + + // Default-Parameter des DC setzen + SetBkColor( dc, ColorTable[0]); + SetBkMode( dc, TRANSPARENT ); + + // Font setzen + SelectObject( dc, PlotFont); + + // Font-Parameter abfragen + if (GetTextMetrics( dc, &tm)) { + graph->fontheight = tm.tmHeight; + graph->fontwidth = tm.tmAveCharWidth; + } + + // Viewport-Parameter setzen + graph->viewport.height = wd->Area.bottom; + graph->viewport.width = wd->Area.right; + + // Absolut-Parameter setzen + graph->absolute.xpos = 0; + graph->absolute.ypos = 0; + graph->absolute.width = wd->Area.right; + graph->absolute.height = wd->Area.bottom; + + // Warten, bis das Fenster wirklich da ist + WaitForIdle(); + + // fertig + return(0); +} + +/****************************************************************************** +WIN_Close ist eigentlich das Gegenstück zu WIN_Init. Dummerweise kann es +passieren, daß (während gerade ein Plot dargestellt wird) WIN_Close aufgerufen +wird, um auf einen Drucker umzuschalten. Deswegen darf WIN_Close nichts machen, +sondern das Auflösen der Strukturen erfolgt bei Programmende. +******************************************************************************/ + +int WIN_Close() +{ + return (0); +} + +void RealClose(void) +{ + // Fensterklasse löschen + if (IsRegistered) { + if (TheWndClass.hIcon) { + DestroyIcon( TheWndClass.hIcon); + TheWndClass.hIcon = NULL; + } + UnregisterClass( WindowName, hInst); + IsRegistered = FALSE; + } +} +#pragma exit RealClose + +int WIN_Clear() +{ + tpWindowData wd; + if (!currentgraph) return 0; + wd = pWindowData(currentgraph); + if (!wd) return 0; + + // das macht das Fenster selbst + if (!wd->PaintFlag) // bei WM_PAINT unnötig + SendMessage( wd->wnd, WM_ERASEBKGND, (WPARAM) wd->hDC, 0); + + return 0; +} + + +int WIN_DrawLine(int x1, int y1, int x2, int y2) +{ + tpWindowData wd; + HPEN OldPen; + HPEN NewPen; + + if (!currentgraph) return 0; + wd = pWindowData(currentgraph); + if (!wd) return 0; + + MoveToEx(wd->hDC, x1, wd->Area.bottom - y1, NULL); + NewPen = CreatePen( LType(wd->ColorIndex), 0, ColorTable[wd->ColorIndex] ); + OldPen = SelectObject(wd->hDC, NewPen); + LineTo(wd->hDC, x2, wd->Area.bottom - y2); + OldPen = SelectObject(wd->hDC, OldPen); + DeleteObject( NewPen); + + return (0); +} + + +int WIN_Arc(int x0, int y0, int radius, double theta1, double theta2) + /* + * Notes: + * Draws an arc of and center at (x0,y0) beginning at + * angle theta1 (in rad) and ending at theta2 + */ +{ + tpWindowData wd; + HPEN OldPen; + HPEN NewPen; + int left, right, top, bottom; + int xs, ys, xe, ye; + int yb; + int direction; + double temp; + double r; + double dx0; + double dy0; + + if (!currentgraph) return 0; + wd = pWindowData(currentgraph); + if (!wd) return 0; + + direction = AD_COUNTERCLOCKWISE; + if (theta1 > theta2) { + temp = theta1; + theta1 = theta2; + theta2 = temp; + direction = AD_CLOCKWISE; + } + SetArcDirection( wd->hDC, direction); + + // Geometrische Vorüberlegungen + yb = wd->Area.bottom; + left = x0 - radius; + right = x0 + radius; + top = y0 + radius; + bottom = y0 - radius; + + r = radius; + dx0 = x0; + dy0 = y0; + xs = (dx0 + (r * cos(theta1))); + ys = (dy0 + (r * sin(theta1))); + xe = (dx0 + (r * cos(theta2))); + ye = (dy0 + (r * sin(theta2))); + + // Zeichnen + NewPen = CreatePen( LType(wd->ColorIndex), 0, ColorTable[wd->ColorIndex] ); + OldPen = SelectObject(wd->hDC, NewPen); + Arc( wd->hDC, left, yb-top, right, yb-bottom, xs, yb-ys, xe, yb-ye); + OldPen = SelectObject(wd->hDC, OldPen); + DeleteObject( NewPen); + + return 0; +} + +int WIN_Text( char * text, int x, int y, int degrees) +{ + tpWindowData wd; + if (!currentgraph) return 0; + wd = pWindowData(currentgraph); + if (!wd) return 0; + + SetTextColor( wd->hDC, ColorTable[wd->ColorIndex]); + TextOut( wd->hDC, x, wd->Area.bottom - y - currentgraph->fontheight, text, strlen(text)); + + return (0); +} + + +int WIN_DefineColor(int red, int green, int blue, int num) +{ + // nix + return (0); +} + +int WIN_DefineLinestyle(int num, int mask) +{ + // nix + return (0); +} + +int WIN_SetLinestyle(int style) +{ + // nix + return (0); +} + +int WIN_SetColor( int color) +{ + tpWindowData wd; + if (!currentgraph) return 0; + wd = pWindowData(currentgraph); + if (!wd) return 0; + + wd->ColorIndex = color % NumWinColors; + + return (0); +} + +int WIN_Update() +{ + tpWindowData wd; + if (!currentgraph) return 0; + wd = pWindowData(currentgraph); + if (!wd) return 0; + + // Nach dem ersten absolvieren von Update() werden durch + // FirstFlag wieder WM_PAINT-Botschaften bearbeitet. + // Dies verhindert doppeltes Zeichnen beim Darstellen des Fensters. + wd->FirstFlag = 0; + return 0; +} + +int WIN_DiagramReady() +{ + return 0; +} + +#endif /* HAS_WINDOWS */ \ No newline at end of file diff --git a/src/frontend/wdisp/winprint.c b/src/frontend/wdisp/winprint.c new file mode 100644 index 000000000..e7b751c29 --- /dev/null +++ b/src/frontend/wdisp/winprint.c @@ -0,0 +1,451 @@ +/* + * Printing Routines for the IBM PC using MS Windows + * Wolfgang Mües 27.10.97 + * Holger Vogt 07.12.01 + */ + +#define STRICT +#include "ngspice.h" + +#ifdef HAS_WINDOWS + +#include "graph.h" +#include "ftedev.h" +#include "ftedbgra.h" +#pragma warn -dup +#include +#include +#include "suffix.h" +#pragma hdrstop + +// Typen +typedef struct { // Extra Printdaten + int ColorIndex; // Index auf die akt. Farbe + int LineIndex; // Index auf den akt. Linientyp +} tPrintData; +typedef tPrintData * tpPrintData; // Zeiger darauf +#define pPrintData(g) ((tpPrintData)(g->devdep)) + +// lokale Variablen +static HFONT PlotFont = NULL; // Font-Merker +static HFONT OldFont = NULL; +#define NumLines 7 // Anzahl der LineStyles +static int LineTable[NumLines]; // Speicher für die LineStyles +static HDC PrinterDC = NULL; // Device Context +#define NumPrintColors 2 // vordef. Farben +static COLORREF ColorTable[NumPrintColors];// Speicher für die Farben +static int PrinterWidth = 1000; // Breite des Papiers +static int PrinterHeight = 1000; // Höhe des Papiers + +/****************************************************************************** + Drucker-Initialisierung +******************************************************************************/ + +void WPRINT_PrintInit(HWND hwnd) +{ + // Parameter-Block + PRINTDLG pd; + + // Initialisieren + pd.lStructSize = sizeof(PRINTDLG); + pd.hwndOwner = hwnd; + pd.hDevMode = NULL; + pd.hDevNames = NULL; + pd.hDC = NULL; + pd.Flags = PD_PRINTSETUP; + pd.nFromPage = 1; + pd.nToPage = 1; + pd.nMinPage = 0; + pd.nMaxPage = 0; + pd.nCopies = 1; + pd.hInstance = NULL; + pd.lCustData = 0; + pd.lpfnPrintHook = NULL; + pd.lpfnSetupHook = NULL; + pd.lpPrintTemplateName = NULL; + pd.lpSetupTemplateName = NULL; + pd.hPrintTemplate = NULL; + pd.hSetupTemplate = NULL; + + // Default-Drucker initialisieren + (void) PrintDlg( &pd); + + // Speicher freigeben + if( pd.hDevMode) GlobalFree( pd.hDevMode); + if( pd.hDevNames) GlobalFree( pd.hDevNames); +} + +// Abort-Procedur zum Drucken +BOOL CALLBACK WPRINT_Abort( HDC hdc, int iError) +{ + // Multitasking + WaitForIdle(); + + // Warten + return TRUE; +} + + +/****************************************************************************** +WPRINT_Init() stellt die Verbindung zur Grafik her. Dazu gehört die Feststellung +von + dispdev->numlinestyles + dispdev->numcolors + dispdev->width + dispdev->height + +WPRINT_Init() gibt 0 zurück, falls kein Fehler auftrat. + +******************************************************************************/ + +int WPRINT_Init( ) +{ + int pWidth; + int pHeight; + + // Printer-DC holen + if (!PrinterDC) { + + // Parameter-Block + PRINTDLG pd; + + // Initialisieren + pd.lStructSize = sizeof(PRINTDLG); + pd.hwndOwner = NULL; + pd.hDevMode = NULL; + pd.hDevNames = NULL; + pd.hDC = NULL; + pd.Flags = PD_NOPAGENUMS | PD_NOSELECTION | PD_RETURNDC; + pd.nFromPage = 1; + pd.nToPage = 1; + pd.nMinPage = 0; + pd.nMaxPage = 0; + pd.nCopies = 1; + pd.hInstance = NULL; + pd.lCustData = 0; + pd.lpfnPrintHook = NULL; + pd.lpfnSetupHook = NULL; + pd.lpPrintTemplateName = NULL; + pd.lpSetupTemplateName = NULL; + pd.hPrintTemplate = NULL; + pd.hSetupTemplate = NULL; + + // Default-Drucker initialisieren + (void) PrintDlg( &pd); + + // Speicher freigeben + if( pd.hDevMode) GlobalFree( pd.hDevMode); + if( pd.hDevNames) GlobalFree( pd.hDevNames); + + // DC holen + PrinterDC = pd.hDC; + if (!PrinterDC) return 1; + + // Abmaße bestimmen + PrinterWidth = GetDeviceCaps( PrinterDC, HORZRES); + PrinterHeight = GetDeviceCaps( PrinterDC, VERTRES); + pWidth = GetDeviceCaps( PrinterDC, HORZSIZE); + pHeight = GetDeviceCaps( PrinterDC, VERTSIZE); + + // Mapping Mode setzen (für Kreise) + if ( pWidth > pHeight) + // Querformat + PrinterWidth = (PrinterHeight * pWidth) / pHeight; + else + // Hochformat + PrinterHeight = (PrinterWidth * pHeight) / pWidth; + + SetMapMode( PrinterDC, MM_ISOTROPIC); + SetWindowExtEx( PrinterDC, PrinterWidth, PrinterHeight, NULL); + SetViewportExtEx( PrinterDC, PrinterWidth, PrinterHeight, NULL); + + // nicht höher als breit zeichnen + if (pWidth < pHeight) { + // Papier im Hochformat + PrinterHeight = PrinterWidth; + } + + // Initialisierungen des Display-Descriptors + dispdev->width = PrinterWidth; + dispdev->height = PrinterHeight; + dispdev->numlinestyles = NumLines; + dispdev->numcolors = NumPrintColors; + + // Farben initialisieren + ColorTable[0] = RGB(255,255,255); // Weiß + ColorTable[1] = RGB( 0, 0, 0); // Schwarz + + // LineStyles initialisieren + LineTable[0] = PS_SOLID; + LineTable[1] = PS_DOT; // Gitter + LineTable[2] = PS_SOLID; // Erste Linie + LineTable[3] = PS_DOT; // Zweite Linie + LineTable[4] = PS_DASH; // usw + LineTable[5] = PS_DASHDOT; + LineTable[6] = PS_DASHDOTDOT; + + // Font + if (!PlotFont) { + PlotFont = CreateFont( 0,0,0,0, FW_DONTCARE, FALSE, FALSE, FALSE, + ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, + PROOF_QUALITY, FIXED_PITCH, NULL); + } + + // Abort-Prozedur setzen + SetAbortProc( PrinterDC, WPRINT_Abort); + } + // fertig + return (0); +} + + +/****************************************************************************** + WPRINT_NewViewport() öffnet den Drucker + + WPRINT_NewViewport() gibt 0 zurück, falls erfolgreich + +******************************************************************************/ + +int WPRINT_NewViewport( GRAPH * graph) +{ + TEXTMETRIC tm; + tpPrintData pd; + DOCINFO di; + + // Parameter testen + if (!graph) return 1; + + // Initialisiere, falls noch nicht geschehen + if (WPRINT_Init() != 0) { + externalerror("Can't initialize Printer."); + return(1); + } + + // Device dep. Info allocieren + pd = calloc(1, sizeof(tPrintData)); + if (!pd) return 1; + graph->devdep = (char *)pd; + + // Setze den Color-Index + pd->ColorIndex = 0; + + // Font setzen + OldFont = SelectObject( PrinterDC, PlotFont); + + // Font-Parameter abfragen + if (GetTextMetrics( PrinterDC, &tm)) { + graph->fontheight = tm.tmHeight; + graph->fontwidth = tm.tmAveCharWidth; + } + + // Setze den Linien-Index + pd->LineIndex = 0; + + // Viewport-Parameter setzen + graph->viewport.height = PrinterHeight; + graph->viewport.width = PrinterWidth; + + // Absolut-Parameter setzen + graph->absolute.xpos = 0; + graph->absolute.ypos = 0; + graph->absolute.width = PrinterWidth; + graph->absolute.height = PrinterHeight; + + // Druckauftrag anmelden + di.cbSize = sizeof( DOCINFO); + di.lpszDocName = graph->plotname; + di.lpszOutput = NULL; + if (StartDoc( PrinterDC, &di) <= 0) return 1; + if (StartPage( PrinterDC) <= 0) return 1; + + // titel drucken + if (graph->plotname) { + UINT align; + align = GetTextAlign( PrinterDC); + SetTextAlign( PrinterDC, TA_RIGHT | TA_TOP | TA_NOUPDATECP); + TextOut( PrinterDC, PrinterWidth-graph->fontwidth, 1, graph->plotname, + strlen(graph->plotname)); + SetTextAlign( PrinterDC, align); + } + + // fertig + return(0); +} + +int WPRINT_Close() +{ + if (PrinterDC) { + EndPage( PrinterDC); + EndDoc( PrinterDC); + if (OldFont) { + SelectObject( PrinterDC, OldFont); + OldFont = NULL; + } + DeleteObject( PlotFont); + DeleteDC( PrinterDC); + PrinterDC = NULL; + } + return (0); +} + + +int WPRINT_Clear() +{ + return 0; +} + + +int WPRINT_DrawLine(int x1, int y1, int x2, int y2) +{ + tpPrintData pd; + HPEN OldPen; + HPEN NewPen; + int ColIndex; + + if (!currentgraph) return 0; + pd = pPrintData(currentgraph); + if (!pd) return 0; + + // Farben/Dicke + ColIndex = pd->ColorIndex; + if (ColIndex > 1) + ColIndex = 1; + + MoveToEx(PrinterDC, x1, PrinterHeight - y1, NULL); + NewPen = CreatePen( LineTable[pd->LineIndex], 0, ColorTable[ColIndex] ); + OldPen = SelectObject(PrinterDC, NewPen); + LineTo(PrinterDC, x2, PrinterHeight - y2); + OldPen = SelectObject(PrinterDC, OldPen); + DeleteObject( NewPen); + return (0); +} + + +int WPRINT_Arc(int x0, int y0, int radius, double theta1, double theta2) + /* + * Notes: + * Draws an arc of and center at (x0,y0) beginning at + * angle theta1 (in rad) and ending at theta2 + */ +{ + tpPrintData pd; + HPEN OldPen; + HPEN NewPen; + int left, right, top, bottom; + int xs, ys, xe, ye; + int yb; + int direction; + int ColIndex; + double temp; + double r; + double dx0; + double dy0; + + if (!currentgraph) return 0; + pd = pPrintData(currentgraph); + if (!pd) return 0; + + ColIndex = pd->ColorIndex; + if (ColIndex > 1) + ColIndex = 1; + + direction = AD_COUNTERCLOCKWISE; + if (theta1 > theta2) { + temp = theta1; + theta1 = theta2; + theta2 = temp; + direction = AD_CLOCKWISE; + } + SetArcDirection( PrinterDC, direction); + + // Geometrische Vorüberlegungen + yb = PrinterHeight; + left = x0 - radius; + right = x0 + radius; + top = y0 + radius; + bottom = y0 - radius; + + r = radius; + dx0 = x0; + dy0 = y0; + xs = (dx0 + (r * cos(theta1))); + ys = (dy0 + (r * sin(theta1))); + xe = (dx0 + (r * cos(theta2))); + ye = (dy0 + (r * sin(theta2))); + + // Zeichnen + NewPen = CreatePen( LineTable[pd->LineIndex], 0, ColorTable[ColIndex] ); + OldPen = SelectObject(PrinterDC, NewPen); + Arc( PrinterDC, left, yb-top, right, yb-bottom, xs, yb-ys, xe, yb-ye); + OldPen = SelectObject(PrinterDC, OldPen); + DeleteObject( NewPen); + + return 0; +} + +int WPRINT_Text( char * text, int x, int y, int degrees) +{ + tpPrintData pd; + int ColIndex; + + if (!currentgraph) return 0; + pd = pPrintData(currentgraph); + if (!pd) return 0; + + ColIndex = pd->ColorIndex; + if (ColIndex > 1) { + ColIndex = 1; + } + + SetTextColor( PrinterDC, ColorTable[ColIndex]); + TextOut( PrinterDC, x, PrinterHeight - y - currentgraph->fontheight, text, strlen(text)); + return (0); +} + + +int WPRINT_DefineColor(int red, int green, int blue, int num) +{ + // nix + return (0); +} + +int WPRINT_DefineLinestyle(int num, int mask) +{ + // nix + return (0); +} + +int WPRINT_SetLinestyle(int style) +{ + tpPrintData pd; + if (!currentgraph) return 0; + pd = pPrintData(currentgraph); + if (!pd) return 0; + + pd->LineIndex = style % NumLines; + return (0); +} + +int WPRINT_SetColor( int color) +{ + tpPrintData pd; + if (!currentgraph) return 0; + pd = pPrintData(currentgraph); + if (!pd) return 0; + + pd->ColorIndex = color; + return (0); +} + +int WPRINT_Update() +{ + return (0); +} + +int WPRINT_DiagramReady() +{ + return 0; +} + +#endif /* HAS_WINDOWS */ + diff --git a/src/include/wstdio.h b/src/include/wstdio.h new file mode 100644 index 000000000..b549a599c --- /dev/null +++ b/src/include/wstdio.h @@ -0,0 +1,97 @@ +/* I/O Redirection für Spice 3F4 unter Win32s + Autor: Wolfgang Mües + Stand: 21.05.95 +*/ + +#ifndef W_STDIO_H +#define W_STDIO_H +#include // originale Definitionen +#undef getc(f) // alte macros zurücknehmen +#undef putc(c,f) +#undef ungetc(c,f) +#undef getchar() +#undef putchar(c) +#undef feof(f) +#undef ferror(f) + + +// ------------------------------------------------------------------ + +int f_c_l_o_s_e( FILE * __stream); +int f_f_l_u_s_h( FILE * __stream); +int fg_e_t_c( FILE * __stream); +int f_g_e_t_p_o_s( FILE * __stream, fpos_t * __pos); +char * fg_e_t_s(char * __s, int __n, FILE * __stream); +int fp_r_i_n_t_f(FILE * __stream, const char * __format, ...); +int fp_u_t_c(int __c, FILE * __stream); +int fp_u_t_s(const char * __s, FILE * __stream); +size_t f_r_e_a_d(void * __ptr, size_t __size, size_t __n, FILE * __stream); +FILE * f_r_e_o_p_e_n(const char * __path, const char * __mode, FILE * __stream); +int fs_c_a_n_f(FILE * __stream, const char * __format, ...); +int f_s_e_e_k(FILE * __stream, long __offset, int __whence); +int f_s_e_t_p_o_s(FILE * __stream, const fpos_t*__pos); +long f_t_e_l_l(FILE * __stream); +size_t f_w_r_i_t_e(const void * __ptr, size_t __size, size_t __n, FILE * __stream); +char * g_e_t_s(char * __s); +void p_e_r_r_o_r(const char * __s); +int p_r_i_n_t_f(const char * __format, ...); +int p_u_t_s(const char * __s); +int s_c_a_n_f(const char * __format, ...); +int ung_e_t_c(int __c, FILE * __stream); +int vfp_r_i_n_t_f(FILE * __stream, const char * __format, void * __arglist); +//int vfs_c_a_n_f(FILE * __stream, const char * __format, void * __arglist); +int vp_r_i_n_t_f(const char * __format, void * __arglist); +//int vs_c_a_n_f(const char * __format, void * __arglist); +int r_e_a_d(int fd, char * __buf, int __n); +int g_e_t_c(FILE * __fp); +int g_e_t_char(void); +int p_u_t_char(const int __c); +int p_u_t_c(const int __c, FILE * __fp); +int f_e_o_f(FILE * __fp); +int f_e_r_r_o_r(FILE * __fp); +int fg_e_t_char(void); +int fp_u_t_char(int __c); + +// --------------------------------------------------------------- + +#define fclose f_c_l_o_s_e +#define fflush f_f_l_u_s_h +#define fgetc fg_e_t_c +#define fgetpos f_g_e_t_p_o_s +#define fgets fg_e_t_s +#define fprintf fp_r_i_n_t_f +#define fputc fp_u_t_c +#define fputs fp_u_t_s +#define fread f_r_e_a_d +#define afreopen f_r_e_o_p_e_n // hvogt 10.05.2000 +#define fscanf fs_c_a_n_f +#define fseek f_s_e_e_k +#define fsetpos f_s_e_t_p_o_s +#define ftell f_t_e_l_l +#define fwrite f_w_r_i_t_e +#define gets g_e_t_s +#define perror p_e_r_r_o_r +#define printf p_r_i_n_t_f +#define puts p_u_t_s +#define scanf s_c_a_n_f +#define ungetc ung_e_t_c +#define vfprintf vfp_r_i_n_t_f +//#define vfscanf vfs_c_a_n_f +#define vprintf vp_r_i_n_t_f +//#define vscanf vs_c_a_n_f +#define read r_e_a_d +#define getc g_e_t_c +#define getchar g_e_t_char +#define putchar p_u_t_char +#define putc p_u_t_c +#define feof f_e_o_f +#define ferror f_e_r_r_o_r +#define fgetchar fg_e_t_char +#define fputchar fp_u_t_char + +// ---------------------------------------------------------------------------- + +// #include "io_special.h" + +#endif /* W_STDIO_H */ + diff --git a/src/winmain.c b/src/winmain.c new file mode 100644 index 000000000..2a0cd5a63 --- /dev/null +++ b/src/winmain.c @@ -0,0 +1,1323 @@ +/* Hauptprogramm für Spice 3F5 unter Windows95 + Autor: Wolfgang Mües + Stand: 28.10.97 + Autor: Holger Vogt + Stand: 01.05.2000 + Stand: 12.12.2001 +*/ +#include "config.h" +#ifdef HAS_WINDOWS + +#define STRICT // strikte Typprüfung +#define WIN32_LEAN_AND_MEAN +#include // normale Windows-Aufrufe +#include // Win32 Message Cracker +//#include // 3D-Steuerelemente +#include // sprintf und co +#include // exit-codes +#include // var. argumente +#include // assert-macro +// #include // shellexecute +//#include // Verzeichnis-Funktionen hvogt 09.12.01 +//#include // argc, argv + + +#include +#include +#pragma hdrstop + +#include + + // bool defined +// Konstanten +#define TBufSize 2048 // Größe des Textbuffers +#define CR VK_RETURN // Carriage Return +#define LF 10 // Line Feed +#define SE 0 // StringEnde +#define BorderSize 8 // Umrandung des Stringfeldes +#define SBufSize 100 // Größe des Stringbuffers +#define IOBufSize 1024 // Größe des printf-Buffers +#define HistSize 20 // Zeilen History-Buffer +#define StatusHeight 25 // Höhe des Status Bars +#define StatusFrame 2 // Abstand Statusbar / StatusElement +#define StatusElHeight (StatusHeight - 2 * StatusFrame) +#define SourceLength 400 // Platz für Source File Name +#define AnalyseLength 100 // Platz für Analyse + +// Typen +typedef char SBufLine[SBufSize+1]; // Eingabezeile + +// Globale Variablen +HINSTANCE hInst; // Instanz der Applikation +int WinLineWidth = 640; // Fensterbreite +HWND hwMain; // Hauptfenster der Applikation +HWND twText; // TextFenster +HWND swString; // Eingabezeile +HWND hwStatus; // Status-Balken +HWND hwSource; // Anzeige des Source-Namens +HWND hwAnalyse; // Anzeige des Analyse-Fensters +static int nReturnCode = 0; // Rückgabewert von WinMain +static int nShowState; // Anzeigemodus des Hauptfensters +static WNDCLASS hwMainClass; // Klassendefinition des Hauptfensters +static LPCTSTR hwClassName = "SPICE_TEXT_WND";// Klassenname des Hauptfensters +static LPCTSTR hwWindowName = "ngspice 14"; // Name des Fensters +static WNDCLASS twTextClass; // Klassendefinition des Textfensters +static LPCTSTR twClassName = "SPICE_TEXT_BOX"; // Klassenname der Textbox +static LPCTSTR twWindowName = "TextOut"; // Name des Fensters +static size_t TBufEnd = 0; // Zeigt auf \0 +static char TBuffer [TBufSize+1]; // Textbuffer +static SBufLine SBuffer; // Eingabebuffer +static WNDCLASS swStringClass; // Klassendefinition des Stringfensters +static LPCTSTR swClassName = "SPICE_STR_IN"; // Klassenname der Texteingabe +static LPCTSTR swWindowName = "StringIn"; // Name des Fensters +static char CRLF [] = { CR, LF, SE} ; // CR/LF +static WNDCLASS hwElementClass; // Klassendefinition der Statusanzeigen +static LPCTSTR hwElementClassName = "ElementClass"; +static LPCTSTR hwSourceWindowName = "SourceDisplay"; +static LPCTSTR hwAnalyseWindowName = "AnalyseDisplay"; +static int RowHeight = 16; // Höhe einer Textzeile +static int LineHeight = 25; // Höhe der Eingabezeile +static int VisibleRows = 10; // Anzahl der sichtbaren Zeilen im Textfenster +static BOOL DoUpdate = FALSE; // Textfenster updaten +static WNDPROC swProc = NULL; // originale Stringfenster-Prozedur +static WNDPROC twProc = NULL; // originale Textfenster-Prozedur +static SBufLine HistBuffer[HistSize]; // History-Buffer fürs Stringfenster +static int HistIndex = 0; // History-Verwaltung +static int HistPtr = 0; // History-Verwaltung + +extern BOOL oflag; // falls 1, Output über stdout in File umgeleitet +extern FILE *flogp; // siehe xmain.c, hvogt 14.6.2000 +int argc; +char *argv[]; +// Forward-Definition von main() +int xmain( int argc, char * argv[]/*, char * env[]*/); +// forward der Update-Funktion +void DisplayText( void); + + +// -------------------------------------------------------- + +// Alle Puffer löschen und Zeiger auf den Anfang setzen +void HistoryInit(void) +{ + int i; + HistIndex = 0; + HistPtr = 0; + for ( i = 0; i < HistSize; i++) + HistBuffer[i][0] = SE; +} + +// Erste Zeile des Buffers löschen; alles rückt auf +void HistoryScroll(void) +{ + memmove( &(HistBuffer[0]), &(HistBuffer[1]), sizeof(SBufLine) * (HistSize-1)); + HistBuffer[HistSize-1][0] = SE; + if (HistIndex) HistIndex--; + if (HistPtr) HistPtr--; +} + +// Neue Eingabezeile in den History-Buffer schreiben +void HistoryEnter( char * newLine) +{ + if (!newLine || !*newLine) return; + if (HistPtr == HistSize) HistoryScroll(); + strcpy( HistBuffer[HistPtr], newLine); + HistPtr++; + HistIndex = HistPtr; +} + +// Mit dem Index eine Zeile zurückgehen und den dort stehenden Eintrag zurückgeben +char * HistoryGetPrev(void) +{ + if (HistIndex) HistIndex--; + return &(HistBuffer[HistIndex][0]); +} + +// Mit dem Index eine Zeile vorgehen und den dort stehenden Eintrag zurückgeben +char * HistoryGetNext(void) +{ + if (HistIndex < HistPtr) HistIndex++; + if (HistIndex == HistPtr) HistIndex--; + return &(HistBuffer[HistIndex][0]); +} + +// ---------------------------------------------------------- + +// Warte, bis keine Messages mehr zu bearbeiten sind +void WaitForIdle(void) +{ + MSG m; + // arbeite alle Nachrichten ab + while ( PeekMessage( &m, NULL, 0, 0, PM_REMOVE)) { + TranslateMessage( &m); + DispatchMessage( &m); + } +} + +// ---------------------------------------------------------- + +// Warte, bis keine Messages mehr zu bearbeiten sind, +// dann warte auf neue Message (Input handling ohne Dauerloop) +void WaitForMessage(void) +{ + MSG m; + // arbeite alle Nachrichten ab + while ( PeekMessage( &m, NULL, 0, 0, PM_REMOVE)) { + TranslateMessage( &m); + DispatchMessage( &m); + } + WaitMessage(); +} + +// ------------------------------------------------------------- + +// Löschen des Stringfensters +void ClearInput(void) +{ + // Darstellen + Edit_SetText( swString, ""); +} + +// -------------------------------------------------------- + +// Neuer Text ins Sourcefile-Fenster +void SetSource( char * Name) +{ + if (hwSource) { + SetWindowText( hwSource, Name); + InvalidateRgn( hwSource, NULL, TRUE); + } +} + +// ----------------------------------------------------------- + +// Neuer Text ins Analysefenster +static int OldPercent = -2; +void SetAnalyse( char * Analyse, int Percent) +{ + char s[128]; + + if (Percent == OldPercent) return; + OldPercent = Percent; + if (hwAnalyse) { + if (Percent < 0) + sprintf( s, "--ready--"); + else + sprintf( s, "%s : %3u%%", Analyse, Percent); + SetWindowText( hwAnalyse, s); + InvalidateRgn( hwAnalyse, NULL, TRUE); + WaitForIdle(); + } +} + +// --------------------------------------------------------------- + +// Anpassen des Scrollers im Textfenster +// Stellt gleichzeitig den Text neu dar +void AdjustScroller(void) +{ + int LineCount; + int FirstLine; + int MyFirstLine; + LineCount = Edit_GetLineCount( twText); + FirstLine = Edit_GetFirstVisibleLine( twText); + MyFirstLine = LineCount - VisibleRows; + if (MyFirstLine < 0 ) MyFirstLine = 0; + Edit_Scroll( twText, MyFirstLine - FirstLine, 0); + // Das wars + DoUpdate = FALSE; +} + +// Löschen einer Zeile im Textbuffer +void _DeleteFirstLine(void) +{ + char * cp = strchr( TBuffer, LF); + if (!cp) { + // Buffer leeren + TBufEnd = 0; + TBuffer[TBufEnd] = SE; + return; + } + cp++; + TBufEnd -= cp - TBuffer; + memmove( TBuffer, cp, TBufEnd); + TBuffer[TBufEnd] = SE; +} + +// Anfügen eines chars an den TextBuffer +void AppendChar( char c) +{ + // Textbuffer nicht zu groß werden lassen + while ((TBufEnd+4) >= TBufSize) + _DeleteFirstLine(); + // Zeichen anfügen + TBuffer[TBufEnd++] = c; + TBuffer[TBufEnd] = SE; + DoUpdate = TRUE; + // Sobald eine Zeile zuende, im Textfenster anzeigen + if (c == LF) + DisplayText(); +} + +// Anfügen eines Strings an den TextBuffer +void AppendString( const char * Line) +{ + size_t i; + if (!Line) return; + + // Zeilenlänge bestimmen + i = strlen(Line); + // Textbuffer nicht zu groß werden lassen + while ((i+TBufEnd+3) >= TBufSize) + _DeleteFirstLine(); + // Zeile dranhängen + strcpy( &TBuffer[TBufEnd], Line); + TBufEnd += i; + DoUpdate = TRUE; +} + +// Text neu darstellen +void DisplayText( void) +{ + // Darstellen + Edit_SetText( twText, TBuffer); + // Scroller updaten, neuen Text darstellen + AdjustScroller(); +} +/* +// Anfügen einer Zeile an den Textbuffer +void AppendLine( const char * Line) +{ + if (!Line) return; + + // String anhängen + AppendString( Line); + + // CRLF anhängen + AppendString( CRLF); +} +*/ +// ------------------------------------------------------------------- + +// Lese ein Zeichen ein +int w_getch(void) +{ + int c; + + // Sind noch Zeichen da? + c = SBuffer[0]; + if (!c) { + // Alte Informationen darstellen + if (DoUpdate) + DisplayText(); + // Focus setzen + SetFocus( swString); + // Cursor = normal + SetCursor( LoadCursor( NULL, IDC_IBEAM)); + // Analyse ist fertig + SetAnalyse( NULL, -1); + // Warten auf die Eingabe + do { + WaitForMessage(); + c = SBuffer[0]; + } while ( !c ); + // Zeichen an die Ausgabe anhängen + AppendString( SBuffer); + // Cursor = warten + SetCursor( LoadCursor( NULL, IDC_WAIT)); + } + // Zeichen abholen + memmove( &SBuffer[0], &SBuffer[1], SBufSize); + return c; +} + +// Gebe ein Zeichen aus +int w_putch( int c) +{ + if (c) + AppendChar( (char)c ); + return c; +} + +// --------------------------------------------------------- + +// Hauptfenster verändert seine Größe +#pragma warn -par +void Main_OnSize(HWND hwnd, UINT state, int cx, int cy) +{ + int h = cy - LineHeight - StatusHeight; + + // Textfenster expandieren + MoveWindow( twText, 0, 0, cx, h , TRUE); + VisibleRows = (h / RowHeight) -1; + AdjustScroller(); + + // Stringfenster expandieren + MoveWindow( swString, 0, h, cx, LineHeight, TRUE); + + // StatusElemente expandieren + h = cy - LineHeight + StatusFrame -1; + MoveWindow( hwSource, StatusFrame, h, SourceLength, StatusElHeight, TRUE); + MoveWindow( hwAnalyse, 3 * StatusFrame + SourceLength, h, AnalyseLength, + StatusElHeight, TRUE); +} + + +// Schreibe einen Befehl in den Spice-Kommandobuffer +void PostSpiceCommand( const char * const cmd) +{ + strcpy( SBuffer, cmd); + strcat( SBuffer, CRLF); +} + +// HauptfensterProzedur +#pragma warn -eff +LRESULT CALLBACK MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + UINT i; + + switch (uMsg) { + + case WM_SYSCOLORCHANGE: +// Ctl3dColorChange(); + goto DEFAULT_AFTER; + + case WM_CLOSE: + // den Spice-Befehl zum Beenden des Programms in den Textbuffer schreiben + PostSpiceCommand( "quit"); + // Unterbrechen, falls Simulation schon läuft, 30.4.2000 hvogt + raise (SIGINT); + return 0; + +/* //gedacht für ctrl C , geht noch nicht + case WM_KEYDOWN: + i = (UINT) wParam; + if ((i == 0x63) && (GetKeyState(VK_CONTROL) < 0)) { + // Interrupt zum Unterbrechen (interaktiv) + // oder Beenden (Batch) des Programms auslösen + raise (SIGINT); + return 0; + } */ + +/* //gedacht für ctrl C , geht noch nicht + case WM_CHAR: + i = (char) wParam; + if ((i == "c") && (GetKeyState(VK_CONTROL) < 0)) { + // Interrupt zum Unterbrechen (interaktiv) + // oder Beenden (Batch) des Programms auslösen + raise (SIGINT); + return 0; + } */ + + case WM_SIZE: + HANDLE_WM_SIZE( hwnd, wParam, lParam, Main_OnSize); + goto DEFAULT_AFTER; + + default: +DEFAULT_AFTER: + return DefWindowProc( hwnd, uMsg, wParam, lParam); + } +} + +// StringfensterProzedur +LRESULT CALLBACK StringWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + char c; + UINT i; + + switch (uMsg) { + + case WM_KEYDOWN: + i = (UINT) wParam; + if ((i == VK_UP) || (i == VK_DOWN)) { + // alten Text neu setzen + SetWindowText( hwnd, i == VK_UP? HistoryGetPrev(): HistoryGetNext()); + // Cursor ans Ende der Zeile + CallWindowProc( swProc, hwnd, uMsg, (WPARAM) VK_END, lParam); + return 0; + } + if ( i == VK_ESCAPE) { + ClearInput(); + return 0; + } + + + goto DEFAULT; + + case WM_CHAR: + c = (char) wParam; + if (c == CR) { + GetWindowText( hwnd, SBuffer, SBufSize); + HistoryEnter( SBuffer); + strcat( SBuffer, CRLF); + ClearInput(); + return 0; + } + if (c == VK_ESCAPE) + return 0; + default: +DEFAULT: + return CallWindowProc( swProc, hwnd, uMsg, wParam, lParam); + } +} + +// TextfensterProzedur +LRESULT CALLBACK TextWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + unsigned char c; + UINT i; + + switch (uMsg) { + + case WM_KEYDOWN: + i = (UINT) wParam; + if ((i == VK_UP) || (i == VK_DOWN) || (i == VK_ESCAPE)) { + // Leite um ins String-Fenster + SetFocus( swString); + return SendMessage( swString, uMsg, wParam, lParam); + } + goto DEFAULT_TEXT; + + case WM_CHAR: + c = (unsigned char) wParam; + if ((c == CR) || ( c >= ' ') || ( c == VK_ESCAPE)) { + // Leite um ins String-Fenster + SetFocus( swString); + return SendMessage( swString, uMsg, wParam, lParam); + } + default: +DEFAULT_TEXT: + return CallWindowProc( twProc, hwnd, uMsg, wParam, lParam); + } +} + + +void Element_OnPaint(HWND hwnd) +{ + PAINTSTRUCT ps; + RECT r; + RECT s; + HGDIOBJ o; + char buffer[128]; + int i; + + // Vorbereiten + HDC hdc = BeginPaint( hwnd, &ps); + GetClientRect( hwnd, &r); + + // Rahmen zeichnen + o = GetStockObject( GRAY_BRUSH); + s.left = r.left; + s.right = r.right; + s.top = r.top; + s.bottom = r.top+1; + FillRect( hdc, &s, o); + + s.right = r.left+1; + s.bottom = r.bottom; + FillRect( hdc, &s, o); + + o = GetStockObject( WHITE_BRUSH); + s.right = r.right; + s.top = r.bottom-1; + FillRect( hdc, &s, o); + + s.left = r.right-1; + s.top = r.top; + FillRect( hdc, &s, o); + + // Inhalt zeichnen + buffer[0] = '\0'; + i = GetWindowText( hwnd, buffer, 127); + s.left = r.left+1; + s.right = r.right-1; + s.top = r.top+1; + s.bottom = r.bottom-1; + o = GetStockObject( LTGRAY_BRUSH); + FillRect( hdc, &s, o); + SetBkMode( hdc, TRANSPARENT); + ExtTextOut( hdc, s.left+1, s.top+1, ETO_CLIPPED, &s, buffer, i, NULL); + + // Ende + EndPaint( hwnd, &ps); +} + + +// ElementfensterProzedur +LRESULT CALLBACK ElementWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) { + + case WM_PAINT: + HANDLE_WM_PAINT(hwnd, wParam, lParam, Element_OnPaint); + return 0; + + default: + return DefWindowProc( hwnd, uMsg, wParam, lParam); + } +} + + +#define SPACE ' ' +#define QUOTE '\"' +#define DELIMITER 26 /* for the lack of anything better */ +#define DELIMITERSTRING "\26" + +/* + This function converts a string into an argc/argv represenation. + INPUT: + cmdline - a string + OUTPUT: + argc - the number of equivalent argv strings + which is also the number of strings in argv + argv - the argv given the input string which + consists of seperate strings for each argument + RETURNS: + 0 on success + -1 on failure +*/ +int MakeArgcArgv(char *cmdline,int *argc,char ***argv) +{ + char *pC1; /* a temporary character pointer */ + char *pC2; /* a temporary character pointer */ + char *pWorkString=NULL; /* a working copy of cmdline */ + int i; /* a loop counter */ + int j; /* a loop counter */ + int quoteflag=0; /* for the finite state machine parsing cmdline */ + int numargs=1; /* the number of command line arguments, later + copied to *argc */ + char **tmpargv; /* the temporary argv, later copied to *argv */ + int status = ERROR_SUCCESS; /* status */ + char buffer[MAX_PATH+1]; + + + /* make sure we aren't dealing with any NULL pointers */ + if ( (NULL == argc) + || (NULL == argv)) + { + status = -1; + goto outahere; + } + *argc = 0; /* set the count to zero to start */ + *argv = NULL; /* set the pointer to NULL to start */ + /* if the string passed in was a NULL pointer, consider this + to be an empty command line and give back only + an argc of 1 and an argv[0] */ + if (NULL != cmdline) + { + /* make a copy of the string so that we can modify it + without messing up the original */ + pWorkString = strdup(cmdline); + if (NULL == pWorkString) + return -1; /* memory allocation error */ + /* Now, to make sure we don't have any quoted arguments + with spaces in them, replace all spaces except those + between " marks with our own special delimiter for + strtok */ + /* trim all the whitespace off the end of the string. */ + for (i=(signed)strlen(pWorkString)-1; i >=0; i--) + if (isspace(pWorkString[i])) + pWorkString[i] = '\0'; + else + break; + /* If we still have a string left, parse it for all + the arguments. */ + if (strlen(pWorkString)) + { + /* This could probably be done with strtok as well + but strtok is destructive if I wanted to look for " \"" + and I couldn't tell what delimiter that I had bumped + against */ + for (i=0; i < (signed)strlen(pWorkString); i++) + { + switch (pWorkString[i]) + { + case SPACE: + if (!quoteflag) + { + pWorkString[i] = DELIMITER; /* change space to delimiter */ + numargs++; + } + break; + case QUOTE: + quoteflag = !quoteflag; /* turns on and off as we pass quotes */ + break; + } + } + /* Now, we should have ctrl-Zs everywhere that + there used to be a space not protected by + quote marks. We should also have the number + of command line arguments that were in the + command line (not including argv[0] which should + be the program name). We should add one more + to numargs to take into account argv[0]. */ + numargs++; + } + } + /* malloc an argv */ + tmpargv = (char**)malloc(numargs * sizeof(char *)); + if (NULL == tmpargv) + { + status = -1; + goto outahere; + } + /* you can put your program name here or find an API to give it + to you if you want. I am just giving a name to fill the space */ + GetModuleFileName(NULL, buffer, sizeof(buffer)); + + +// tmpargv[0] = strdup("ngspice"); + tmpargv[0] = buffer; + + pC1 = NULL; + /* Now actually strdup all the arguments out of the sting + and store them in the argv */ + for (i=1; i < numargs; i++) + { + if (NULL == pC1) + pC1 = pWorkString; + for (j=0; j < (signed)strlen(pC1); j++) + { + if (DELIMITER == pC1[j]) + { + pC1[j] = '\0'; + pC2 = &pC1[j+1]; + break; + } + } + tmpargv[i] = strdup(pC1); + if (NULL == tmpargv[i]) + { + status = -1; + goto outahere; + } + pC1 = pC2; + } + /* copy the working values over to the arguments */ + *argc = numargs; + *argv = tmpargv; +outahere: + /* free the working string if one was allocated */ + if (pWorkString) + free(pWorkString); + /* return status */ + return status; +} + + + +// Unser main +#pragma warn -par +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) +{ + int i; + int status; + + int argc; + char **argv; + + + + // globale Variablen füllen + hInst = hInstance; + nShowState = nCmdShow; + + // Textbuffer initialisieren + TBufEnd = 0; + TBuffer[TBufEnd] = SE; + SBuffer[0] = SE; + HistoryInit(); + + // 3D-Elemente registrieren +// Ctl3dRegister( hInstance); +// Ctl3dAutoSubclass( hInstance); + + // Hauptfensterklasse definieren + hwMainClass.style = CS_HREDRAW | CS_VREDRAW; + hwMainClass.lpfnWndProc = MainWindowProc; + hwMainClass.cbClsExtra = 0; + hwMainClass.cbWndExtra = 0; + hwMainClass.hInstance = hInst; + hwMainClass.hIcon = LoadIcon( hInst, MAKEINTRESOURCE(1)); + hwMainClass.hCursor = LoadCursor( NULL, IDC_ARROW); + hwMainClass.hbrBackground = GetStockObject( LTGRAY_BRUSH); + hwMainClass.lpszMenuName = NULL; + hwMainClass.lpszClassName = hwClassName; + if (!RegisterClass( &hwMainClass)) goto THE_END; + + // Textfensterklasse definieren + if (!GetClassInfo( NULL, "EDIT", &twTextClass)) goto THE_END; + twProc = twTextClass.lpfnWndProc; + twTextClass.lpfnWndProc = TextWindowProc; + twTextClass.hInstance = hInst; + twTextClass.lpszMenuName = NULL; + twTextClass.lpszClassName = twClassName; + if (!RegisterClass( &twTextClass)) goto THE_END; + + // Stringfensterklasse definieren + if (!GetClassInfo( NULL, "EDIT", &swStringClass)) goto THE_END; + swProc = swStringClass.lpfnWndProc; + swStringClass.lpfnWndProc = StringWindowProc; + swStringClass.hInstance = hInst; + swStringClass.lpszMenuName = NULL; + swStringClass.lpszClassName = swClassName; + if (!RegisterClass( &swStringClass)) goto THE_END; + + // StatusElementklasse definieren + hwElementClass.style = CS_HREDRAW | CS_VREDRAW; + hwElementClass.lpfnWndProc = ElementWindowProc; + hwElementClass.cbClsExtra = 0; + hwElementClass.cbWndExtra = 0; + hwElementClass.hInstance = hInst; + hwElementClass.hIcon = NULL; + hwElementClass.hCursor = LoadCursor( NULL, IDC_ARROW); + hwElementClass.hbrBackground = GetStockObject( LTGRAY_BRUSH); + hwElementClass.lpszMenuName = NULL; + hwElementClass.lpszClassName = hwElementClassName; + if (!RegisterClass( &hwElementClass)) goto THE_END; + + // Hauptfenster kreieren + i = GetSystemMetrics( SM_CYSCREEN) / 3; + hwMain = CreateWindow( hwClassName, hwWindowName, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, + 0, i * 2, GetSystemMetrics( SM_CXSCREEN), i, NULL, NULL, hInst, NULL); + if (!hwMain) goto THE_END; + + // Textfenster kreieren + twText = CreateWindowEx(WS_EX_NOPARENTNOTIFY, twClassName, twWindowName, + ES_LEFT | ES_MULTILINE | ES_READONLY | WS_CHILD | WS_BORDER | WS_VSCROLL, + 20,20,300,100, hwMain, NULL, hInst, NULL); + if (!twText) goto THE_END; + // Ansii fixed font + { + HDC textDC; + HFONT font; + TEXTMETRIC tm; + font = GetStockFont( ANSI_FIXED_FONT); + SetWindowFont( twText, font, FALSE); + textDC = GetDC( twText); + if (textDC) { + SelectObject( textDC, font); + if (GetTextMetrics( textDC, &tm)) { + RowHeight = tm.tmHeight; + WinLineWidth = 90 * tm.tmAveCharWidth; + } + ReleaseDC( twText, textDC); + } + } + + // Stringfenster kreieren + swString = CreateWindowEx(WS_EX_NOPARENTNOTIFY, swClassName, swWindowName, + ES_LEFT | WS_CHILD | WS_BORDER, 20,20,300,100, hwMain, NULL, hInst, NULL); + if (!swString) goto THE_END; + { + HDC stringDC; + TEXTMETRIC tm; + stringDC = GetDC( swString); + if (stringDC) { + if (GetTextMetrics( stringDC, &tm)) + LineHeight = tm.tmHeight + tm.tmExternalLeading + BorderSize; + ReleaseDC( swString, stringDC); + } + } + + // Sourcefenster kreieren + hwSource = CreateWindowEx(WS_EX_NOPARENTNOTIFY, hwElementClassName, + hwSourceWindowName, WS_CHILD, 0,0, SourceLength, StatusElHeight, hwMain, + NULL, hInst, NULL); + if (!hwSource) goto THE_END; + + + // Analysefenster kreieren + hwAnalyse = CreateWindowEx(WS_EX_NOPARENTNOTIFY, hwElementClassName, + hwAnalyseWindowName, WS_CHILD, 0,0, AnalyseLength, StatusElHeight, hwMain, + NULL, hInst, NULL); + if (!hwAnalyse) goto THE_END; + + + // Hauptfenster mit Unterfenstern sichtbar machen + if (WinLineWidth > 600) WinLineWidth = 600; + MoveWindow( hwMain, 0, ((GetSystemMetrics( SM_CYSCREEN) / 3) * 2 - 22), WinLineWidth, + GetSystemMetrics( SM_CYSCREEN) / 3, FALSE); + ShowWindow( hwMain, nShowState); + ShowWindow( twText, SW_SHOWNORMAL); + ShowWindow( swString, SW_SHOWNORMAL); + ShowWindow( hwSource, SW_SHOWNORMAL); + ShowWindow( hwAnalyse,SW_SHOWNORMAL); + ClearInput(); + DisplayText(); + SetSource( ""); +// SetAnalyse( NULL, -1); + SetAnalyse(" ", 0); + UpdateWindow( hwMain); + SetFocus( swString); + + status = MakeArgcArgv(lpszCmdLine,&argc,&argv); + + + // Warten, bis alles klar ist + WaitForIdle(); + + // Ab nach main() + nReturnCode = xmain(argc, argv/*, _environ*/); + + +THE_END: + // 3D abschalten +// Ctl3dUnregister( hInstance); + + // terminate + return nReturnCode; +} + + +// ------------------------------------------------------------------- + +/* Eigentlich wollte ich die Standard-Streams durch einen Hook in der Library umleiten, + aber so etwas gibt es anscheinend nicht. Deswegen muß ich praktisch alle + IO-Funktionen umdefinieren (siehe wstdio.h). Leider geht das nicht bei allen. + Man schaue also nach, bevor man eine Funktion benutzt! +*/ + +int f_f_l_u_s_h( FILE * __stream) +{ + if (((__stream == stdout) && (oflag == FALSE)) || (__stream == stderr)) + return 0; + else + return fflush(__stream); +} + +int fg_e_t_c( FILE * __stream) +{ + if (__stream == stdin) { + int c; + do { + c = w_getch(); + } while( c == CR); + return c; + } else + return fgetc(__stream); +} + +int f_g_e_t_p_o_s( FILE * __stream, fpos_t * __pos) +{ + int result; + if ((__stream == stdin) || ((__stream == stdout) && (oflag == FALSE)) || (__stream == stderr)) { + assert(FALSE); + return 0; + } else + result = fgetpos(__stream, __pos); + return result; +} + +char * fg_e_t_s(char * __s, int __n, FILE * __stream) +{ + if (__stream == stdin) { + int i = 0; + int c; + while ( i < (__n-1)) { + c = w_getch(); + if (c == LF) { + __s[i++] = LF; + break; + } + if (c != CR) + __s[i++] = (char)c; + } + __s[i] = SE; + return __s; + } else + return fgets( __s, __n, __stream); +} + +int fp_u_t_c(int __c, FILE * __stream) +{ + if ((oflag == FALSE) && ((__stream == stdout) || (__stream == stderr))) { + if ( __c == LF) + w_putch( CR); + return w_putch(__c); +// Ausgabe in Datei *.log 14.6.2000 + } else if ((oflag == TRUE) && ((__stream == stdout) || __stream == stderr)) { + return fputc( __c, flogp); + } else + return fputc( __c, __stream); +} + +int fp_u_t_s(const char * __s, FILE * __stream) +{ +// if (((__stream == stdout) && (oflag == FALSE)) || (__stream == stderr)) { hvogt 14.6.2000 + if ((__stream == stdout) || (__stream == stderr)) { + + int c = SE; + if (!__s) return EOF; + do { + if (*__s) { + c = *__s++; + fp_u_t_c(c, __stream); + } else + return c; + } while (TRUE); + } else + return fputs( __s, __stream); +} + +int fp_r_i_n_t_f(FILE * __stream, const char * __format, ...) +{ + int result; + char s [IOBufSize]; + va_list args; + va_start(args, __format); + +// if (((__stream == stdout) && (oflag == FALSE)) || (__stream == stderr)) { + if ((__stream == stdout) || (__stream == stderr)) { + + s[0] = SE; + result = vsprintf( s, __format, args); + fp_u_t_s( s, __stream); + } else + result = vfprintf( __stream, __format, args); + + va_end(args); + return result; +} + +int f_c_l_o_s_e( FILE * __stream) +{ + if ((__stream == stdin) || ((__stream == stdout) && (oflag == FALSE)) || (__stream == stderr)) { + assert(FALSE); + return 0; + } + return fclose( __stream); +} + +size_t f_r_e_a_d(void * __ptr, size_t __size, size_t __n, FILE * __stream) +{ +// if ((__stream == stdin) || ((__stream == stdout) && (oflag == FALSE)) || (__stream == stderr)) { + if (((__stream == stdout) && (oflag == FALSE)) || (__stream == stderr)) { + assert(FALSE); + return 0; + } + + if (__stream == stdin) { + int i = 0; + int c; + char s [IOBufSize]; + while ( i < (__size * __n - 1)) { + c = w_getch(); + if (c == LF) { +// s[i++] = LF; + break; + } + if (c != CR) + s[i++] = (char)c; + } +// s[i] = SE; + __ptr = &s[0]; + return (int)(i/__size); + } + return fread( __ptr, __size, __n, __stream); +} + +FILE * f_r_e_o_p_e_n(const char * __path, const char * __mode, FILE * __stream) +{ + if ((__stream == stdin)/* || ((__stream == stdout) && (oflag == FALSE)) || (__stream == stderr)*/) { + assert(FALSE); + return 0; + } + return freopen( __path, __mode, __stream); +} + +int fs_c_a_n_f(FILE * __stream, const char * __format, ...) +{ + int result; + va_list args; + va_start(args, __format); + if ((__stream == stdin) || ((__stream == stdout) && (oflag == FALSE)) || (__stream == stderr)) { + assert(FALSE); + return 0; + } + result = fscanf( __stream, __format, args); + va_end(args); + return result; +} + +int f_s_e_e_k(FILE * __stream, long __offset, int __whence) +{ + if ((__stream == stdin) || ((__stream == stdout) && (oflag == FALSE)) || (__stream == stderr)) { + assert(FALSE); + return 0; + } + return fseek( __stream, __offset, __whence); +} + +int f_s_e_t_p_o_s(FILE * __stream, const fpos_t *__pos) +{ + if ((__stream == stdin) || ((__stream == stdout) && (oflag == FALSE)) || (__stream == stderr)) { + assert(FALSE); + return 0; + } + return fsetpos( __stream, __pos); +} + +long f_t_e_l_l(FILE * __stream) +{ + if ((__stream == stdin) || ((__stream == stdout) && (oflag == FALSE)) || (__stream == stderr)) { + assert(FALSE); + return 0; + } + return ftell( __stream); +} + +size_t f_w_r_i_t_e(const void * __ptr, size_t __size, size_t __n, FILE * __stream) +{ +// p_r_i_n_t_f("entered fwrite, size %d, n %d \n", __size, __n); + if (__stream == stdin) { + assert(FALSE); +// p_r_i_n_t_f("False \n"); + return 0; + } + if ((__stream == stdout) || (__stream == stderr)) { + char * __s = __ptr; + int c = SE; + int i = 0; + char *out; + +// p_r_i_n_t_f("test1 %s\n", __s); + + if (!__s) return EOF; + for (i = 0; i< (__size * __n); i++) { + if (*__s) { + c = *__s++; + fp_u_t_c(c, __stream); + } else + break; + }; +// f_r_e_a_d(out, __size, __n, __stream); +// p_r_i_n_t_f("test2 %s", out); + return (int)(i/__size); + } +// p_r_i_n_t_f("test3 %s\n", __ptr); + return fwrite( __ptr, __size, __n, __stream); +} + +char * g_e_t_s(char * __s) +{ + return fg_e_t_s( __s, 10000, stdin); +} + +void p_e_r_r_o_r(const char * __s) +{ + const char * cp; +/* cp = _strerror( __s); + fp_u_t_s( cp, stderr); */ + cp = strerror(errno); + fp_r_i_n_t_f(stderr, "%s: %s\n", __s, cp); + // nur als Test für NT +// fp_u_t_s("Test für NT: perror, weiter mit RETURN\n", stderr); +// fg_e_t_c(stdin); +} + +int p_r_i_n_t_f(const char * __format, ...) +{ + int result; + char s [IOBufSize]; + va_list args; + va_start(args, __format); + + s[0] = SE; + result = vsprintf( s, __format, args); + fp_u_t_s( s, stdout); + va_end(args); + return result; +} + +int p_u_t_s(const char * __s) +{ + return fp_u_t_s( __s, stdout); +} + +int s_c_a_n_f(const char * __format, ...) +{ + assert( FALSE); + return FALSE; +} + +int ung_e_t_c(int __c, FILE * __stream) +{ + assert( FALSE); + return FALSE; +} + +int vfp_r_i_n_t_f(FILE * __stream, const char * __format, void * __arglist) +{ + int result; + char s [IOBufSize]; + + s[0] = SE; +// if (((__stream == stdout) && (oflag == FALSE)) || (__stream == stderr)) { + if ((__stream == stdout) || (__stream == stderr)) { + + result = vsprintf( s, __format, __arglist); + fp_u_t_s( s, stdout); + } else + result = vfprintf( __stream, __format, __arglist); + return result; +} + +/*int vfs_c_a_n_f(FILE * __stream, const char * __format, void * __arglist) +{ + if (__stream == stdin) { + assert(FALSE); + return 0; + } + return vfscanf( __stream, __format, __arglist); +} +*/ +int vp_r_i_n_t_f(const char * __format, void * __arglist) +{ + int result; + char s [IOBufSize]; + + s[0] = SE; + result = vsprintf( s, __format, __arglist); + fp_u_t_s( s, stdout); + return result; +} + +/*int vs_c_a_n_f(const char * __format, void * __arglist) +{ + assert( FALSE); + return FALSE; +} */ + +int r_e_a_d(int fd, char * __buf, int __n) +{ + if (fd == 0) { + int i = 0; + int c; + char s [IOBufSize]; + while ( i < __n ) { + c = w_getch(); + if (c == LF) { +// s[i++] = LF; + break; + } + if (c != CR) + s[i++] = (char)c; + } +// s[i] = SE; + __buf = &s[0]; + return (i); + } + else { + return read(fd, __buf, __n); + } +} +int g_e_t_c(FILE * __fp) +{ + return fg_e_t_c( __fp); +} + +int g_e_t_char(void) +{ + return fg_e_t_c( stdin); +} + +int p_u_t_char(const int __c) +{ + return fp_u_t_c( __c, stdout); +} + +int p_u_t_c(const int __c, FILE * __fp) +{ + return fp_u_t_c( __c, __fp); +} + +int f_e_o_f(FILE * __fp) +{ + if ((__fp == stdin) || (__fp == stdout) || (__fp == stderr)) { + assert(FALSE); + return 0; + } + return feof( __fp); +} + +int f_e_r_r_o_r(FILE * __fp) +{ + if ((__fp == stdin) || (__fp == stdout) || (__fp == stderr)) { + assert(FALSE); + return 0; + } + return ferror( __fp); +} + +int fg_e_t_char(void) +{ + return fg_e_t_c( stdin); +} + +int fp_u_t_char(int __c) +{ + return fp_u_t_c( __c, stdout); +} + +// ------------------------------------------------------ +/* +size_t _memavl(void) +{ + MEMORYSTATUS ms; + DWORD sum; + ms.dwLength = sizeof(MEMORYSTATUS); + GlobalMemoryStatus( &ms); + sum = ms.dwAvailPhys + ms.dwAvailPageFile; + return (size_t) sum; +} +*/ +// -------------------------------------------- + +int system( const char * command) +{ + // info-Blöcke + STARTUPINFO si; + PROCESS_INFORMATION pi; + DWORD ExitStatus; + + // Datenstrukturen füllen + memset( &si, 0, sizeof( STARTUPINFO)); + si.cb = sizeof( STARTUPINFO); + memset( &pi, 0, sizeof( PROCESS_INFORMATION)); + + // starte den neuen Prozess + if (!CreateProcess( + NULL, // address of module name + (char *) command, // address of command line + NULL, // address of process security attributes + NULL, // address of thread security attributes + FALSE, // new process inherits handles + NORMAL_PRIORITY_CLASS, // creation flags + NULL, // address of new environment block + NULL, // address of current directory name + &si, // address of STARTUPINFO + &pi // address of PROCESS_INFORMATION + )) return -1; + + // dieses Handle muß da sein + if (!pi.hProcess) return -1; + + do { + // Multitasking ermöglichen + WaitForIdle(); + // hole mir den Exit-Code des Prozesses + if (!GetExitCodeProcess( pi.hProcess, &ExitStatus)) return -1; + // solange er existiert + } while( ExitStatus == STILL_ACTIVE); + + // Handles freigeben + if (pi.hThread) CloseHandle( pi.hThread); + if (pi.hProcess) CloseHandle( pi.hProcess); + + // fertig + return 0; +} // system Windows95 + +#endif /* HAS_WINDOWS */ +