[PATCH #56] New history buffering
This commit is contained in:
parent
aaf7af790b
commit
e0039e12da
200
src/winmain.c
200
src/winmain.c
|
|
@ -19,15 +19,17 @@
|
||||||
#include <assert.h> // assert macro
|
#include <assert.h> // assert macro
|
||||||
#include "ngspice/stringutil.h" // copy
|
#include "ngspice/stringutil.h" // copy
|
||||||
#include <io.h> // _read
|
#include <io.h> // _read
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/timeb.h>
|
#include <sys/timeb.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "hist_info.h" /* history management */
|
||||||
#include "ngspice/bool.h" /* bool defined as unsigned char */
|
#include "ngspice/bool.h" /* bool defined as unsigned char */
|
||||||
#include "misc/misc_time.h" /* timediff */
|
#include "misc/misc_time.h" /* timediff */
|
||||||
|
#include "winmain.h"
|
||||||
|
|
||||||
/* Constants */
|
/* Constants */
|
||||||
#define TBufSize 65536 // size of text buffer
|
#define TBufSize 65536 // size of text buffer
|
||||||
|
|
@ -38,7 +40,8 @@
|
||||||
#define BorderSize 8 // Umrandung des Stringfeldes
|
#define BorderSize 8 // Umrandung des Stringfeldes
|
||||||
#define SBufSize 100 // Groesze des Stringbuffers
|
#define SBufSize 100 // Groesze des Stringbuffers
|
||||||
#define IOBufSize 16348 // Groesze des printf-Buffers
|
#define IOBufSize 16348 // Groesze des printf-Buffers
|
||||||
#define HistSize 20 // Zeilen History-Buffer
|
#define HIST_SIZE 20 /* Max # commands held in history */
|
||||||
|
#define N_BYTE_HIST_BUF 512 /* Initial size of history buffer in bytes */
|
||||||
#define StatusHeight 25 // Hoehe des Status Bars
|
#define StatusHeight 25 // Hoehe des Status Bars
|
||||||
#define StatusFrame 2 // Abstand Statusbar / StatusElement
|
#define StatusFrame 2 // Abstand Statusbar / StatusElement
|
||||||
#define StatusElHeight (StatusHeight - 2 * StatusFrame)
|
#define StatusElHeight (StatusHeight - 2 * StatusFrame)
|
||||||
|
|
@ -46,6 +49,11 @@
|
||||||
#define AnalyseLength 100 // Platz fuer Analyse
|
#define AnalyseLength 100 // Platz fuer Analyse
|
||||||
#define QuitButtonLength 80
|
#define QuitButtonLength 80
|
||||||
|
|
||||||
|
/* Define the macro below to create a larger main window that is useful
|
||||||
|
* for seeing debug output that is generated before the window can be
|
||||||
|
* resized */
|
||||||
|
//#define BIG_WINDOW_FOR_DEBUGGING
|
||||||
|
|
||||||
/* macro to ignore unused variables and parameters */
|
/* macro to ignore unused variables and parameters */
|
||||||
#define NG_IGNORE(x) (void)x
|
#define NG_IGNORE(x) (void)x
|
||||||
|
|
||||||
|
|
@ -89,9 +97,6 @@ static int VisibleRows = 10; /* Number of visible lines in text window
|
||||||
static BOOL DoUpdate = FALSE; /* Update text window */
|
static BOOL DoUpdate = FALSE; /* Update text window */
|
||||||
static WNDPROC swProc = NULL; /* original string window procedure */
|
static WNDPROC swProc = NULL; /* original string window procedure */
|
||||||
static WNDPROC twProc = NULL; /* original text window procedure */
|
static WNDPROC twProc = NULL; /* original text window procedure */
|
||||||
static SBufLine HistBuffer[HistSize]; /* History buffer for string window */
|
|
||||||
static int HistIndex = 0; /* History management */
|
|
||||||
static int HistPtr = 0; /* History management */
|
|
||||||
|
|
||||||
extern bool ft_ngdebug; /* some additional debug info printed */
|
extern bool ft_ngdebug; /* some additional debug info printed */
|
||||||
extern bool ft_batchmode;
|
extern bool ft_batchmode;
|
||||||
|
|
@ -99,72 +104,11 @@ extern FILE *flogp; /* definition see xmain.c, stdout redirected to file */
|
||||||
|
|
||||||
extern void cp_doquit(void);
|
extern void cp_doquit(void);
|
||||||
|
|
||||||
#include "winmain.h"
|
|
||||||
|
|
||||||
/* --------------------------<history management>------------------------------ */
|
|
||||||
|
|
||||||
/* Clear history buffer, set pointer to the beginning */
|
|
||||||
static void
|
|
||||||
HistoryInit(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
HistIndex = 0;
|
|
||||||
HistPtr = 0;
|
|
||||||
for (i = 0; i < HistSize; i++)
|
|
||||||
HistBuffer[i][0] = SE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Delete first line of buffer, all other lines move one down */
|
static struct History_info *init_history(void);
|
||||||
static void
|
|
||||||
HistoryScroll(void)
|
|
||||||
{
|
|
||||||
memmove(&(HistBuffer[0]), &(HistBuffer[1]), sizeof(SBufLine) * (HistSize-1));
|
|
||||||
HistBuffer[HistSize-1][0] = SE;
|
|
||||||
if (HistIndex)
|
|
||||||
HistIndex--;
|
|
||||||
if (HistPtr)
|
|
||||||
HistPtr--;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Enter new input line into history buffer */
|
|
||||||
static void
|
|
||||||
HistoryEnter(char *newLine)
|
|
||||||
{
|
|
||||||
if (!newLine || !*newLine)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (HistPtr == HistSize)
|
|
||||||
HistoryScroll();
|
|
||||||
|
|
||||||
strcpy(HistBuffer[HistPtr], newLine);
|
|
||||||
HistPtr++;
|
|
||||||
HistIndex = HistPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Mit dem Index eine Zeile zurueckgehen und den dort stehenden Eintrag zurueckgeben
|
|
||||||
static char *
|
|
||||||
HistoryGetPrev(void)
|
|
||||||
{
|
|
||||||
if (HistIndex)
|
|
||||||
HistIndex--;
|
|
||||||
return &(HistBuffer[HistIndex][0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Mit dem Index eine Zeile vorgehen und den dort stehenden Eintrag zurueckgeben
|
|
||||||
static char *
|
|
||||||
HistoryGetNext(void)
|
|
||||||
{
|
|
||||||
if (HistIndex < HistPtr)
|
|
||||||
HistIndex++;
|
|
||||||
if (HistIndex == HistPtr)
|
|
||||||
return ""; //HistIndex--;
|
|
||||||
return &(HistBuffer[HistIndex][0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------<Message Handling>-------------------------------
|
// ---------------------------<Message Handling>-------------------------------
|
||||||
|
|
||||||
|
|
@ -532,16 +476,21 @@ MainWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
static LRESULT CALLBACK
|
static LRESULT CALLBACK
|
||||||
StringWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
StringWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
char c;
|
static struct History_info **pp_hi; /* handle to history */
|
||||||
UINT i;
|
|
||||||
|
|
||||||
switch (uMsg) {
|
switch (uMsg) {
|
||||||
|
case WM_CREATE:
|
||||||
case WM_KEYDOWN:
|
/* Get access to history information */
|
||||||
i = (UINT) wParam;
|
pp_hi = (struct History_info **)
|
||||||
|
((LPCREATESTRUCT) lParam)->lpCreateParams;
|
||||||
|
break;
|
||||||
|
case WM_KEYDOWN: {
|
||||||
|
const UINT i = (UINT) wParam;
|
||||||
if ((i == VK_UP) || (i == VK_DOWN)) {
|
if ((i == VK_UP) || (i == VK_DOWN)) {
|
||||||
/* Set old text to new */
|
/* Set old text to new */
|
||||||
SetWindowText(hwnd, (i == VK_UP) ? HistoryGetPrev() : HistoryGetNext());
|
SetWindowText(hwnd, (i == VK_UP) ?
|
||||||
|
history_get_prev(*pp_hi, NULL) :
|
||||||
|
history_get_next(*pp_hi, NULL));
|
||||||
/* Put cursor to end of line */
|
/* Put cursor to end of line */
|
||||||
CallWindowProc(swProc, hwnd, uMsg, (WPARAM) VK_END, lParam);
|
CallWindowProc(swProc, hwnd, uMsg, (WPARAM) VK_END, lParam);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -550,10 +499,10 @@ StringWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
ClearInput();
|
ClearInput();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
goto DEFAULT;
|
break;
|
||||||
|
}
|
||||||
case WM_CHAR:
|
case WM_CHAR: {
|
||||||
c = (char) wParam;
|
const char c = (char) wParam;
|
||||||
if (c == CR) {
|
if (c == CR) {
|
||||||
/* Get text from the window. Must leave space for crlf
|
/* Get text from the window. Must leave space for crlf
|
||||||
* that is appended. -1 accounts for NULL as follows:
|
* that is appended. -1 accounts for NULL as follows:
|
||||||
|
|
@ -563,7 +512,26 @@ StringWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
* counted in the size needed for the CRLF string. */
|
* counted in the size needed for the CRLF string. */
|
||||||
const int n_char_returned = GetWindowText(
|
const int n_char_returned = GetWindowText(
|
||||||
hwnd, SBuffer, sizeof SBuffer - (sizeof CRLF - 1));
|
hwnd, SBuffer, sizeof SBuffer - (sizeof CRLF - 1));
|
||||||
HistoryEnter(SBuffer);
|
unsigned int n_char_prev_cmd;
|
||||||
|
|
||||||
|
/* Add the command to the history if it is different from the
|
||||||
|
* previous one. This avoids filling the buffer with the same
|
||||||
|
* command and allows faster scrolling through the commands.
|
||||||
|
* history_get_newest() is called rather than history_get_prev()
|
||||||
|
* since the current return position may not be the last one
|
||||||
|
* and the position should not be changed. */
|
||||||
|
const char *cmd_prev = history_get_newest(
|
||||||
|
*pp_hi, &n_char_prev_cmd);
|
||||||
|
if ((int) n_char_prev_cmd != n_char_returned ||
|
||||||
|
strcmp(SBuffer, cmd_prev) != 0) {
|
||||||
|
/* Different, so add */
|
||||||
|
history_add(pp_hi, n_char_returned, SBuffer);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
history_reset_pos(*pp_hi);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
strcpy(SBuffer + n_char_returned, CRLF);
|
strcpy(SBuffer + n_char_returned, CRLF);
|
||||||
ClearInput();
|
ClearInput();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -583,10 +551,11 @@ StringWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
raise (SIGINT);
|
raise (SIGINT);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
DEFAULT:
|
|
||||||
return CallWindowProc(swProc, hwnd, uMsg, wParam, lParam);
|
|
||||||
}
|
}
|
||||||
|
} /* end of switch over handled messages */
|
||||||
|
|
||||||
|
/* Fowrard to be processed further by swProc */
|
||||||
|
return CallWindowProc(swProc, hwnd, uMsg, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -849,12 +818,18 @@ WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
|
||||||
_In_ LPSTR lpszCmdLine, _In_ int nCmdShow)
|
_In_ LPSTR lpszCmdLine, _In_ int nCmdShow)
|
||||||
{
|
{
|
||||||
int ix, iy; /* width and height of screen */
|
int ix, iy; /* width and height of screen */
|
||||||
int iyt; /* height of screen divided by 3 */
|
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
int argc;
|
int argc;
|
||||||
char **argv;
|
char **argv;
|
||||||
|
|
||||||
|
/* Initialize history info to a maximum of HIST_SIZE commands.
|
||||||
|
* The initial buffer for storage is N_BYTE_HIST_BUF bytes. */
|
||||||
|
struct History_info *p_hi = init_history();
|
||||||
|
if (p_hi == (struct History_info *) NULL) {
|
||||||
|
goto THE_END;
|
||||||
|
}
|
||||||
|
|
||||||
RECT wsize; /* size of usable window */
|
RECT wsize; /* size of usable window */
|
||||||
|
|
||||||
NG_IGNORE(hPrevInstance);
|
NG_IGNORE(hPrevInstance);
|
||||||
|
|
@ -867,7 +842,6 @@ WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
|
||||||
TBufEnd = 0;
|
TBufEnd = 0;
|
||||||
TBuffer[TBufEnd] = SE;
|
TBuffer[TBufEnd] = SE;
|
||||||
SBuffer[0] = SE;
|
SBuffer[0] = SE;
|
||||||
HistoryInit();
|
|
||||||
|
|
||||||
/* Define main window class */
|
/* Define main window class */
|
||||||
hwMainClass.style = CS_HREDRAW | CS_VREDRAW;
|
hwMainClass.style = CS_HREDRAW | CS_VREDRAW;
|
||||||
|
|
@ -926,15 +900,21 @@ WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
|
||||||
goto THE_END;
|
goto THE_END;
|
||||||
|
|
||||||
/*Create main window */
|
/*Create main window */
|
||||||
SystemParametersInfo(SPI_GETWORKAREA, 0, &wsize, 0);
|
|
||||||
iy = wsize.bottom;
|
|
||||||
iyt = iy / 3;
|
|
||||||
ix = wsize.right;
|
|
||||||
// iy = GetSystemMetrics(SM_CYSCREEN);
|
// iy = GetSystemMetrics(SM_CYSCREEN);
|
||||||
// iyt = GetSystemMetrics(SM_CYSCREEN) / 3;
|
// iyt = GetSystemMetrics(SM_CYSCREEN) / 3;
|
||||||
// ix = GetSystemMetrics(SM_CXSCREEN);
|
// ix = GetSystemMetrics(SM_CXSCREEN);
|
||||||
|
SystemParametersInfo(SPI_GETWORKAREA, 0, &wsize, 0);
|
||||||
|
iy = wsize.bottom;
|
||||||
|
ix = wsize.right;
|
||||||
|
#ifndef BIG_WINDOW_FOR_DEBUGGING
|
||||||
|
const int iyt = iy / 3; /* height of screen divided by 3 */
|
||||||
hwMain = CreateWindow(hwClassName, hwWindowName, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
|
hwMain = CreateWindow(hwClassName, hwWindowName, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
|
||||||
0, iyt * 2, ix, iyt, NULL, NULL, hInst, NULL);
|
0, iyt * 2, ix, iyt, NULL, NULL, hInst, NULL);
|
||||||
|
#else
|
||||||
|
hwMain = CreateWindow(hwClassName, hwWindowName, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
|
||||||
|
0, 0, ix, iy, NULL, NULL, hInst, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!hwMain)
|
if (!hwMain)
|
||||||
goto THE_END;
|
goto THE_END;
|
||||||
|
|
||||||
|
|
@ -963,13 +943,15 @@ WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create string window for input */
|
/* Create string window for input. Give a handle to history info to
|
||||||
|
* the window for saving and retrieving commands */
|
||||||
swString = CreateWindowEx(WS_EX_NOPARENTNOTIFY, swClassName, swWindowName,
|
swString = CreateWindowEx(WS_EX_NOPARENTNOTIFY, swClassName, swWindowName,
|
||||||
ES_LEFT | WS_CHILD | WS_BORDER |
|
ES_LEFT | WS_CHILD | WS_BORDER |
|
||||||
ES_AUTOHSCROLL, /* Allow text to scroll */
|
ES_AUTOHSCROLL, /* Allow text to scroll */
|
||||||
20, 20, 300, 100, hwMain, NULL, hInst, NULL);
|
20, 20, 300, 100, hwMain, NULL, hInst, &p_hi);
|
||||||
if (!swString)
|
if (!swString) {
|
||||||
goto THE_END;
|
goto THE_END;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
HDC stringDC;
|
HDC stringDC;
|
||||||
|
|
@ -1009,7 +991,9 @@ WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
|
||||||
Limit window to screen size (if only VGA). */
|
Limit window to screen size (if only VGA). */
|
||||||
if (WinLineWidth > ix)
|
if (WinLineWidth > ix)
|
||||||
WinLineWidth = ix;
|
WinLineWidth = ix;
|
||||||
|
#ifndef BIG_WINDOW_FOR_DEBUGGING
|
||||||
MoveWindow(hwMain, 0, (iyt * 2), WinLineWidth, iyt, FALSE);
|
MoveWindow(hwMain, 0, (iyt * 2), WinLineWidth, iyt, FALSE);
|
||||||
|
#endif
|
||||||
ShowWindow(hwMain, nShowState);
|
ShowWindow(hwMain, nShowState);
|
||||||
ShowWindow(twText, SW_SHOWNORMAL);
|
ShowWindow(twText, SW_SHOWNORMAL);
|
||||||
ShowWindow(swString, SW_SHOWNORMAL);
|
ShowWindow(swString, SW_SHOWNORMAL);
|
||||||
|
|
@ -1031,14 +1015,44 @@ WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
|
||||||
/* Go to main() */
|
/* Go to main() */
|
||||||
nReturnCode = xmain(argc, argv);
|
nReturnCode = xmain(argc, argv);
|
||||||
|
|
||||||
THE_END:
|
THE_END:
|
||||||
|
|
||||||
/* terminate */
|
/* terminate */
|
||||||
|
|
||||||
|
/* Free history information if initialized */
|
||||||
|
if (p_hi != (struct History_info *) NULL) {
|
||||||
|
history_free(p_hi);
|
||||||
|
}
|
||||||
|
|
||||||
return nReturnCode;
|
return nReturnCode;
|
||||||
} /* end of function WinMain */
|
} /* end of function WinMain */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* This funtion initializes the history buffering with a welcome command */
|
||||||
|
static struct History_info *init_history(void)
|
||||||
|
{
|
||||||
|
static struct History_info_opt hi_opt = {
|
||||||
|
sizeof hi_opt,
|
||||||
|
HIST_SIZE, HIST_SIZE, N_BYTE_HIST_BUF,
|
||||||
|
4, 20, 10
|
||||||
|
};
|
||||||
|
|
||||||
|
struct History_info *p_hi = history_init(&hi_opt);
|
||||||
|
if (p_hi == (struct History_info *) NULL) {
|
||||||
|
return (struct History_info *) NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Initialize history buffer with a greeting */
|
||||||
|
static const char cmd_welcome[] = "# Welcome to ngspice!";
|
||||||
|
(void) history_add(&p_hi, sizeof cmd_welcome - 1, cmd_welcome);
|
||||||
|
}
|
||||||
|
|
||||||
|
return p_hi;
|
||||||
|
} /* end of function init_history */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------<User-IO>--------------------------------
|
// -----------------------------------<User-IO>--------------------------------
|
||||||
|
|
||||||
/* Eigentlich wollte ich die Standard-Streams durch einen Hook in der Library umleiten,
|
/* Eigentlich wollte ich die Standard-Streams durch einen Hook in der Library umleiten,
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,6 @@ static char* rlead(char*);
|
||||||
|
|
||||||
void winmessage(char*);
|
void winmessage(char*);
|
||||||
|
|
||||||
static void HistoryInit(void);
|
|
||||||
static void HistoryScroll(void);
|
|
||||||
static void HistoryEnter(char *newLine);
|
|
||||||
static char *HistoryGetPrev(void);
|
|
||||||
static char *HistoryGetNext(void);
|
|
||||||
void WaitForIdle(void);
|
void WaitForIdle(void);
|
||||||
static void WaitForMessage(void);
|
static void WaitForMessage(void);
|
||||||
static void ClearInput(void);
|
static void ClearInput(void);
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue