home *** CD-ROM | disk | FTP | other *** search
- /*
- * This file forms part of "TKERN" - "Troy's Kernel for Windows".
- *
- * Copyright (C) 1994 Troy Rollo <troy@cbme.unsw.EDU.AU>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- #include <windows.h>
- #include <windowsx.h>
- #include <memory.h>
- #include <string.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <sys/tfile.h>
- #include <sys/tdevice.h>
- #include <sys/tkwin.h>
-
- void far tkern_deliver_signal( int nDevice,
- int nFile,
- int nSignal);
-
- static BOOL bRegistered = 0;
- static int iDevice;
-
- extern HINSTANCE hInstance;
- extern int nError;
-
- extern void UnlockManager(void);
- extern void LockManager(void);
- extern void FlushMessages(void);
- extern void tkern_wakeup_call(void);
-
- static int window_destroy(HWND hWnd);
-
- #define SC_COPY 5000
- #define SC_PASTE 5001
- #define SC_COPYPASTE 5002
-
- #define DEF_MAXLINES 100
- #define DEF_SCROLLLINES 5
-
- struct line
- {
- struct line *plNext;
- struct line *plPrev;
- char *pchLine;
- };
-
- struct per_window
- {
- struct line *pw_head;
- struct line *pw_tail;
- struct line *pw_inhead;
- struct line *pw_intail;
- struct line *pw_history;
- struct line *pw_hishead;
- struct line *pw_histail;
- int nUnscrolledLines;
- int nHistory;
- int nHistMax;
- int nScrollLines;
- int nLines; /* Counter so we can keep the list reasonable */
- int nLinesMax;
- int cxChar;
- int cyChar;
- int nScrollPos;
- HWND hEdit;
- int xEditStart;
- POINT ptMarkStart;
- POINT ptMarkEnd;
- BOOL bMarkValid;
- BOOL bHaveMouse;
- BOOL bProgramClosed;
- };
-
- #define ENTER_HIT WM_USER + 1000
- #define UP_HIT WM_USER + 1001
- #define DOWN_HIT WM_USER + 1002
-
- WNDPROC NormalEditWndProc = 0;
-
- FARPROC FakeEditThunk = 0;
-
- int far pascal _export
- FakeEditWndProc( HWND hWnd,
- UINT wMsg,
- WPARAM wParam,
- LPARAM lParam)
- {
- if (wMsg == WM_KEYDOWN)
- {
- if (wParam == VK_UP)
- {
- SendMessage(GetParent(hWnd), UP_HIT, 0, 0);
- return 0;
- }
- else if (wParam == VK_DOWN)
- {
- SendMessage(GetParent(hWnd), DOWN_HIT, 0, 0);
- return 0;
- }
- }
- if (wMsg == WM_CHAR)
- {
- if (wParam == VK_RETURN)
- {
- SendMessage(GetParent(hWnd), ENTER_HIT, 0, 0);
- return 0;
- }
- else if (wParam == VK_TAB)
- {
- SendMessage(hWnd, EM_REPLACESEL, 0, (long) "\t");
- return 0;
- }
- else if (wParam == 3)
- {
- tkern_deliver_signal(iDevice,
- (int) GetParent(hWnd),
- 2);
- return 0;
- }
- }
- return (*NormalEditWndProc)(hWnd, wMsg, wParam, lParam);
- }
-
- static void
- MoveMark(struct per_window *pw,
- int nLines)
- {
- if (pw->bMarkValid)
- {
- pw->ptMarkStart.y += nLines;
- pw->ptMarkEnd.y += nLines;
- }
- }
-
- static void
- screen_to_row( HWND hWnd,
- struct per_window *pw,
- int x,
- int y,
- int *xOut,
- int *yOut)
- {
- RECT rcClient;
- int cyLastRow;
- struct line *pl;
- int i, j;
-
- GetClientRect(hWnd, &rcClient);
-
- y = rcClient.bottom - y;
- cyLastRow = pw->cyChar + pw->cyChar / 5 * 2;
- if (y < cyLastRow)
- {
- *yOut = 0;
- }
- else
- {
- *yOut = (y - cyLastRow) / pw->cyChar + 1;
- }
-
- if (*yOut > 0)
- *yOut += pw->nScrollPos;
-
- for (i = *yOut, pl = pw->pw_tail;
- i && pl;
- i--, pl = pl->plPrev);
-
- if (!pl || !pl->pchLine)
- {
- *xOut = 0;
- return;
- }
-
- x = x / pw->cxChar;
-
- for (i = j = 0; x > j && pl->pchLine[i]; i++)
- {
- if (pl->pchLine[i] == '\t')
- j += 8 - j % 8;
- else
- j++;
- }
- *xOut = i;
- }
-
- static void
- RedrawPoints( HWND hWnd,
- struct per_window *pw,
- POINT ptStart_,
- POINT ptEnd_)
- {
- POINT ptStart, ptEnd;
- RECT rcRedraw;
-
- if (ptStart_.y > ptEnd_.y)
- {
- ptStart = ptStart_;
- ptEnd = ptEnd_;
- }
- else if (ptStart_.y < ptEnd_.y)
- {
- ptStart = ptEnd_;
- ptEnd = ptStart_;
- }
- else if (ptStart_.x < ptEnd_.x)
- {
- ptStart = ptStart_;
- ptEnd = ptEnd_;
- }
- else
- {
- ptStart = ptEnd_;
- ptEnd = ptStart_;
- }
- if (ptEnd.y > 0)
- {
- ptEnd.y -= pw->nScrollPos;
- if (ptEnd.y < 0)
- ptEnd.y = 0;
- }
- if (ptStart.y > 0)
- {
- ptStart.y -= pw->nScrollPos;
- if (ptStart.y < 1)
- ptStart.y = 1;
- }
-
- if (ptStart.y < ptEnd.y)
- return;
- GetClientRect(hWnd, &rcRedraw);
- rcRedraw.top = rcRedraw.bottom - pw->cyChar * (ptStart.y + 1) - pw->cyChar / 5 * 2;
- if (ptEnd.y)
- rcRedraw.bottom -= pw->cyChar * ptEnd.y + pw->cyChar / 5 * 2;
- InvalidateRect(hWnd, &rcRedraw, TRUE);
- }
-
- static void
- MouseDown( HWND hWnd,
- struct per_window *pw,
- int x,
- int y)
- {
- if (pw->bMarkValid)
- {
- pw->bMarkValid = FALSE;
- RedrawPoints(hWnd, pw, pw->ptMarkStart, pw->ptMarkEnd);
- }
- screen_to_row(hWnd, pw, x, y, &pw->ptMarkStart.x, &pw->ptMarkStart.y);
- pw->ptMarkEnd = pw->ptMarkStart;
- RedrawPoints(hWnd, pw, pw->ptMarkStart, pw->ptMarkEnd);
- SetCapture(hWnd);
- pw->bHaveMouse = TRUE;
- pw->bMarkValid = TRUE;
- }
-
- static void
- MouseMove( HWND hWnd,
- struct per_window *pw,
- int x,
- int y)
- {
- POINT ptTemp;
-
- ptTemp = pw->ptMarkEnd;
- screen_to_row(hWnd, pw, x, y, &pw->ptMarkEnd.x, &pw->ptMarkEnd.y);
- RedrawPoints(hWnd, pw, ptTemp, pw->ptMarkEnd);
- }
-
- static void
- MouseUp(struct per_window *pw)
- {
- ReleaseCapture();
- pw->bHaveMouse = FALSE;
- }
-
-
- static void
- get_mark_coordinates( struct per_window *pw,
- POINT *ptOne,
- POINT *ptTwo)
- {
- if (pw->ptMarkStart.y > pw->ptMarkEnd.y)
- {
- *ptOne = pw->ptMarkStart;
- *ptTwo = pw->ptMarkEnd;
- }
- else if (pw->ptMarkStart.y < pw->ptMarkEnd.y)
- {
- *ptOne = pw->ptMarkEnd;
- *ptTwo = pw->ptMarkStart;
- }
- else if (pw->ptMarkStart.x < pw->ptMarkEnd.x)
- {
- *ptOne = pw->ptMarkStart;
- *ptTwo = pw->ptMarkEnd;
- }
- else
- {
- *ptOne = pw->ptMarkEnd;
- *ptTwo = pw->ptMarkStart;
- }
- }
-
-
- static int
- is_in_mark( int iRow,
- struct per_window *pw,
- int *iMarkBoundary1,
- int *iMarkBoundary2)
- {
- POINT ptStart, ptEnd;
-
- if (!pw->bMarkValid)
- return 0;
- get_mark_coordinates(pw, &ptStart, &ptEnd);
- if (ptStart.y > ptEnd.y)
- {
- if (ptEnd.y > iRow ||
- ptStart.y < iRow)
- return 0;
- if (ptStart.y == iRow)
- {
- *iMarkBoundary1 = ptStart.x;
- return 1;
- }
- if (ptEnd.y == iRow)
- {
- *iMarkBoundary1 = ptEnd.x;
- return 2;
- }
- return 3;
- }
- else if (ptStart.y == iRow)
- {
- *iMarkBoundary1 = ptStart.x;
- *iMarkBoundary2 = ptEnd.x;
- return 4;
- }
- else
- {
- return 0;
- }
- }
-
- static void
- PlaceEdit( HWND hWnd,
- struct per_window *pw)
- {
- RECT rcLoc;
-
- GetClientRect(hWnd, &rcLoc);
- rcLoc.left = pw->xEditStart;
- rcLoc.top = rcLoc.bottom - pw->cyChar - pw->cyChar / 5;
- if (pw->hEdit)
- {
- MoveWindow(pw->hEdit,
- rcLoc.left, rcLoc.top,
- rcLoc.right - rcLoc.left + 1,
- rcLoc.bottom - rcLoc.top + 1,
- TRUE);
- }
- else
- {
- pw->hEdit = CreateWindow( "EDIT",
- "",
- WS_VISIBLE |
- WS_CHILD |
- ES_AUTOHSCROLL |
- ES_LEFT,
- rcLoc.left,
- rcLoc.top,
- rcLoc.right - rcLoc.left,
- rcLoc.bottom - rcLoc.top,
- hWnd,
- (HMENU) 100,
- hInstance,
- 0
- );
- if (!NormalEditWndProc)
- {
- NormalEditWndProc = (WNDPROC)
- GetWindowLong(pw->hEdit, GWL_WNDPROC);
- }
- if (!FakeEditThunk)
- {
- FakeEditThunk = MakeProcInstance((FARPROC) FakeEditWndProc, hInstance);
- }
- SetWindowLong(pw->hEdit, GWL_WNDPROC, (long) FakeEditThunk);
- }
- }
-
- static void
- PaintWindow( HWND hWnd,
- struct per_window *pw)
- {
- PAINTSTRUCT ps;
- TEXTMETRIC tm;
- LOGFONT lf;
- int cyChar;
- int cyInch;
- int yLocation;
- int nRows;
- RECT rcClient;
- HFONT hFont, hOldFont;
- int iRow, iTemp, iTotal;
- struct line *pl;
- LONG xExtent, xExtent2;
- BOOL bBottom = TRUE;
- int iMarkBoundary1, iMarkBoundary2;
- COLORREF crBG, crFG, crFGHigh, crBGHigh;
-
- crFG = GetSysColor(COLOR_WINDOWTEXT);
- crBG = GetSysColor(COLOR_WINDOW);
- crFGHigh = GetSysColor(COLOR_HIGHLIGHTTEXT);
- crBGHigh = GetSysColor(COLOR_HIGHLIGHT);
- if (pw->nUnscrolledLines)
- {
- if (!pw->nScrollPos)
- ScrollWindow(hWnd, 0, -pw->nUnscrolledLines * pw->cyChar, 0, 0);
- pw->nUnscrolledLines = 0;
- PlaceEdit(hWnd, pw);
- UpdateWindow(hWnd);
- }
- BeginPaint(hWnd, &ps);
-
- cyInch = GetDeviceCaps(ps.hdc, LOGPIXELSY);
-
- memset(&lf, 0, sizeof(lf));
- lf.lfHeight = MulDiv(cyInch, 12, 72);
- strcpy(lf.lfFaceName, "System");
- lf.lfPitchAndFamily = FIXED_PITCH;
- hFont = CreateFontIndirect(&lf);
- hOldFont = SelectFont(ps.hdc, hFont);
- GetTextMetrics(ps.hdc, &tm);
- cyChar = tm.tmHeight + tm.tmExternalLeading;
- GetClientRect(hWnd, &rcClient);
- pw->cxChar = tm.tmAveCharWidth;
- pw->cyChar = cyChar;
- pl = pw->pw_tail;
-
- if (pw->pw_tail->pchLine)
- xExtent = GetTabbedTextExtent(ps.hdc,
- pl->pchLine,
- strlen(pl->pchLine),
- 0, 0);
- else
- xExtent = 0;
- pw->xEditStart = LOWORD(xExtent);
-
- PlaceEdit(hWnd, pw);
-
- nRows = (rcClient.bottom - ps.rcPaint.top) / cyChar + 1;
-
- for (iRow = 0, iTotal = 0, pl = pw->pw_tail,
- yLocation = rcClient.bottom - cyChar;
- pl && iTotal < nRows;
- iRow++, iTotal++, pl = pl->plPrev)
- {
- if (iRow == 1 && pw->nScrollPos)
- {
- for (iTemp = 0; iTemp < pw->nScrollPos && pl; iTemp++, pl = pl->plPrev, iRow++);
- if (!pl)
- break;
- }
- if (bBottom)
- {
- yLocation -= cyChar / 5;
- }
- if (pl->pchLine)
- {
- switch(is_in_mark(iRow, pw, &iMarkBoundary1, &iMarkBoundary2))
- {
- case 0: /* Not in a marked area */
- SetTextColor(ps.hdc, crFG);
- SetBkColor(ps.hdc, crBG);
- TabbedTextOut(ps.hdc, 0, yLocation,
- pl->pchLine, strlen(pl->pchLine),
- 0, 0, 0);
- break;
-
- case 1: /* First line in a marked area */
- SetTextColor(ps.hdc, crFG);
- SetBkColor(ps.hdc, crBG);
- TabbedTextOut(ps.hdc, 0, yLocation,
- pl->pchLine, iMarkBoundary1,
- 0, 0, 0);
- xExtent = GetTabbedTextExtent(ps.hdc,
- pl->pchLine,
- iMarkBoundary1,
- 0, 0);
- SetTextColor(ps.hdc, crFGHigh);
- SetBkColor(ps.hdc, crBGHigh);
- TabbedTextOut(ps.hdc, LOWORD(xExtent), yLocation,
- pl->pchLine + iMarkBoundary1,
- strlen(pl->pchLine) - iMarkBoundary1,
- 0, 0, 0);
- break;
-
- case 2: /* Last line in a marked area */
- SetTextColor(ps.hdc, crFGHigh);
- SetBkColor(ps.hdc, crBGHigh);
- TabbedTextOut(ps.hdc, 0, yLocation,
- pl->pchLine, iMarkBoundary1,
- 0, 0, 0);
- xExtent = GetTabbedTextExtent(ps.hdc,
- pl->pchLine,
- iMarkBoundary1,
- 0, 0);
- SetTextColor(ps.hdc, crFG);
- SetBkColor(ps.hdc, crBG);
- TabbedTextOut(ps.hdc, LOWORD(xExtent), yLocation,
- pl->pchLine + iMarkBoundary1,
- strlen(pl->pchLine) - iMarkBoundary1,
- 0, 0, 0);
- break;
-
- case 3: /* Entire line is in a marked area */
- SetTextColor(ps.hdc, crFGHigh);
- SetBkColor(ps.hdc, crBGHigh);
- TabbedTextOut(ps.hdc, 0, yLocation,
- pl->pchLine, strlen(pl->pchLine),
- 0, 0, 0);
- break;
-
- case 4: /* Both first and last line in marked area */
- SetTextColor(ps.hdc, crFG);
- SetBkColor(ps.hdc, crBG);
- TabbedTextOut(ps.hdc, 0, yLocation,
- pl->pchLine, iMarkBoundary1,
- 0, 0, 0);
- xExtent = GetTabbedTextExtent(ps.hdc,
- pl->pchLine,
- iMarkBoundary1,
- 0, 0);
- SetTextColor(ps.hdc, crFGHigh);
- SetBkColor(ps.hdc, crBGHigh);
- TabbedTextOut(ps.hdc, LOWORD(xExtent), yLocation,
- pl->pchLine + iMarkBoundary1,
- iMarkBoundary2 - iMarkBoundary1,
- 0, 0, 0);
- xExtent2 = GetTabbedTextExtent(ps.hdc,
- pl->pchLine + iMarkBoundary1,
- iMarkBoundary2 - iMarkBoundary1,
- 0, 0);
- SetTextColor(ps.hdc, crFG);
- SetBkColor(ps.hdc, crBG);
- TabbedTextOut(ps.hdc, LOWORD(xExtent) + LOWORD(xExtent2),
- yLocation,
- pl->pchLine + iMarkBoundary2,
- strlen(pl->pchLine) - iMarkBoundary2,
- 0, 0, 0);
- break;
- }
- }
- yLocation -= cyChar;
- if (bBottom)
- {
- yLocation -= cyChar / 5;
- bBottom = FALSE;
- }
- }
-
- SelectFont(ps.hdc, hOldFont);
- DeleteFont(hFont);
- EndPaint(hWnd, &ps);
- }
-
- void
- GotLine(struct per_window *pw)
- {
- struct line *plTemp, *plNew;
- char *pchData;
- int nLen;
-
- pw->pw_history = 0;
- nLen = GetWindowTextLength(pw->hEdit);
-
- /* Once for the input queue */
- pchData = (char *) malloc(nLen + 1);
- GetWindowText(pw->hEdit, pchData, nLen + 1);
- pchData[nLen] = 0;
- plNew = (struct line *) malloc(sizeof(struct line));
- plNew->plNext = 0;
- plNew->plPrev = pw->pw_intail;
- plNew->pchLine = pchData;
- if (pw->pw_intail)
- pw->pw_intail->plNext = plNew;
- else
- pw->pw_inhead = plNew;
- pw->pw_intail = plNew;
-
- /* Once for the history list */
- pchData = (char *) malloc(nLen + 1);
- GetWindowText(pw->hEdit, pchData, nLen + 1);
- pchData[nLen] = 0;
- plNew = (struct line *) malloc(sizeof(struct line));
- plNew->plNext = 0;
- plNew->plPrev = pw->pw_histail;
- plNew->pchLine = pchData;
- if (pw->pw_histail)
- pw->pw_histail->plNext = plNew;
- else
- pw->pw_hishead = plNew;
- pw->pw_histail = plNew;
- if (pw->nHistory >= pw->nHistMax)
- {
- plTemp = pw->pw_hishead;
- pw->pw_hishead = plTemp->plNext;
- pw->pw_hishead->plPrev = 0;
- if (plTemp->pchLine)
- free(plTemp->pchLine);
- free(plTemp);
- }
- else
- {
- pw->nHistory++;
- }
- SetWindowText(pw->hEdit, "");
- tkern_wakeup_call();
- }
-
- static BOOL
- CopyText( HWND hWnd,
- struct per_window *pw)
- {
- POINT ptStart;
- POINT ptEnd;
- int i;
- int j;
- int nBytes;
- struct line *pl, *plSaved;
- HGLOBAL hmem;
- char *pchData;
-
- if (!pw->bMarkValid)
- {
- MessageBeep(MB_ICONSTOP);
- return FALSE;
- }
- if (!OpenClipboard(hWnd))
- {
- MessageBeep(MB_ICONEXCLAMATION);
- return FALSE;
- }
- EmptyClipboard();
-
- /* The clipboard wants CRLF separated lines. Figure out
- * how many characters it will be.
- */
-
- get_mark_coordinates(pw, &ptStart, &ptEnd);
-
- for (pl = pw->pw_tail, i = 0; pl && i < ptStart.y; pl = pl->plPrev, i++);
- plSaved = pl;
-
- nBytes = 1; /* For the terminating NUL (not NULL) byte */
-
- while (i >= ptEnd.y)
- {
- nBytes += (pl->pchLine ? strlen(pl->pchLine) : 0);
- if (ptEnd.y == i)
- nBytes -= (pl->pchLine ? (strlen(pl->pchLine) - ptEnd.x) : 0);
- else
- nBytes += 2;
- if (ptStart.y == i)
- nBytes -= ptStart.x;
-
- i--;
- pl = pl->plNext;
- }
-
- hmem = GlobalAlloc(GMEM_MOVEABLE, nBytes);
- pchData = GlobalLock(hmem);
-
- i = ptStart.y;
- pl = plSaved;
-
- while (i >= ptEnd.y)
- {
- if (i == ptStart.y)
- j = ptStart.x;
- else
- j = 0;
-
- if (i == ptEnd.y)
- {
- if (pl->pchLine)
- {
- strncpy(pchData, pl->pchLine + j, ptEnd.x - j);
- pchData += ptEnd.x - j;
- }
- }
- else
- {
- if (pl->pchLine)
- {
- strcpy(pchData, pl->pchLine + j);
- pchData += strlen(pchData);
- }
- *pchData++ = '\r';
- *pchData++ = '\n';
- }
- i--;
- pl = pl->plNext;
- }
- *pchData = '\0';
-
- GlobalUnlock(hmem);
- SetClipboardData(CF_TEXT, hmem);
- CloseClipboard();
- return TRUE;
- }
-
- static void
- PasteText( HWND hWnd,
- struct per_window *pw)
- {
- HGLOBAL hmem;
- char *pchData;
- char *pchEOL;
- char *pchRemainder = 0;
- char *pchNow;
- char *pchTemp;
- int nTemp;
- int iRemainder;
- DWORD dwSelection;
-
- if (!OpenClipboard(hWnd))
- {
- MessageBeep(MB_ICONEXCLAMATION);
- return;
- }
-
- hmem = GetClipboardData(CF_TEXT);
- if (!hmem)
- {
- MessageBeep(MB_ICONSTOP);
- return;
- }
-
- pchData = GlobalLock(hmem);
-
- while ((pchEOL = strchr(pchData, '\r')) != 0)
- {
- pchNow = malloc(pchEOL - pchData + 1);
- strncpy(pchNow, pchData, pchEOL - pchData);
- pchNow[pchEOL - pchData] = 0;
- SendMessage(pw->hEdit, EM_REPLACESEL, 0, (long) pchNow);
- free(pchNow);
-
- /* Remove the tail end of the line. This will get stuck
- * back in once we get to the end of all this.
- *
- * Note that if we have done this once already, we know
- * the selection is theoretically at the end of the window.
- */
-
- if (!pchRemainder)
- {
- dwSelection = SendMessage(pw->hEdit, EM_GETSEL, 0, 0);
- iRemainder = HIWORD(dwSelection);
- nTemp = GetWindowTextLength(pw->hEdit);
- pchTemp = malloc(nTemp + 1);
- GetWindowText(pw->hEdit, pchTemp, nTemp + 1);
- pchRemainder = malloc(nTemp - iRemainder + 1);
- strcpy(pchRemainder, pchTemp + iRemainder);
- pchTemp[iRemainder] = 0;
- SetWindowText(pw->hEdit, pchTemp);
- free(pchTemp);
- }
-
- GotLine(pw);
- pchData = pchEOL + 1;
- if (*pchData == '\n')
- pchData++;
- }
-
- SendMessage(pw->hEdit, EM_REPLACESEL, 0, (long) pchData);
- if (pchRemainder)
- {
- iRemainder = GetWindowTextLength(pw->hEdit);
- SendMessage(pw->hEdit, EM_REPLACESEL, 0, (long) pchRemainder);
- SendMessage(pw->hEdit, EM_SETSEL, TRUE, MAKELPARAM(iRemainder, iRemainder));
- free(pchRemainder);
- }
- }
-
- static void
- Scroll( HWND hWnd,
- struct per_window *pw,
- WPARAM wParam,
- int nPos)
- {
- int nNewPos;
- RECT rcScroll;
- int nRows;
-
- nNewPos = pw->nScrollPos;
- GetClientRect(hWnd, &rcScroll);
- rcScroll.bottom -= pw->cyChar + pw->cyChar / 5;
- nRows = rcScroll.bottom / pw->cyChar - 1;
-
- switch(wParam)
- {
- case SB_BOTTOM:
- nNewPos = 0;
- break;
-
- case SB_LINEDOWN:
- nNewPos--;
- break;
-
- case SB_LINEUP:
- nNewPos++;
- break;
-
- case SB_PAGEUP:
- nNewPos += nRows - 1;
- break;
-
- case SB_PAGEDOWN:
- nNewPos -= nRows - 1;
- break;
-
- case SB_THUMBPOSITION:
- nNewPos = nPos;
- break;
-
- case SB_TOP:
- nNewPos = pw->nLines;
- break;
- }
- if (nNewPos > pw->nLines)
- nNewPos = pw->nLines;
- if (nNewPos < 0)
- nNewPos = 0;
-
- SetScrollPos(hWnd, SB_VERT, pw->nLines - nNewPos, TRUE);
- if (abs(pw->nScrollPos - nNewPos) >= nRows)
- InvalidateRect(hWnd, &rcScroll, TRUE);
- else
- ScrollWindow(hWnd, 0,
- pw->cyChar * (nNewPos - pw->nScrollPos),
- &rcScroll, &rcScroll);
- pw->nScrollPos = nNewPos;
- if (nNewPos > 0)
- pw->nUnscrolledLines = 0;
- }
-
-
- LRESULT CALLBACK _export
- WindowProc( HWND hWnd,
- UINT wMsg,
- WPARAM wParam,
- LPARAM lParam)
- {
- struct per_window *pw;
- PAINTSTRUCT ps;
- TEXTMETRIC tm;
- HDC hdc;
-
- pw = (struct per_window *) GetWindowLong(hWnd, 0);
- switch(wMsg)
- {
- case WM_CREATE:
- hdc = GetDC(hWnd);
- GetTextMetrics(hdc, &tm);
- ReleaseDC(hWnd, hdc);
- pw = (struct per_window *) malloc(sizeof(struct per_window));
- memset(pw, 0, sizeof(struct per_window));
- pw->cxChar = tm.tmAveCharWidth;
- pw->cyChar = tm.tmHeight + tm.tmExternalLeading;
- pw->pw_head = (struct line *) malloc(sizeof(struct line));
- pw->pw_tail = pw->pw_head;
- pw->pw_head->plNext = pw->pw_head->plPrev = 0;
- pw->pw_head->pchLine = 0;
- pw->nHistMax = 20;
- pw->nScrollLines = DEF_SCROLLLINES;
- pw->nLinesMax = DEF_MAXLINES;
- pw->nLines = 1;
- pw->nUnscrolledLines = 0;
- SetWindowLong(hWnd, 0, (long) pw);
- PlaceEdit(hWnd, pw);
- break;
-
- case WM_CLOSE:
- if (!pw->bProgramClosed)
- {
- MessageBeep(MB_ICONSTOP);
- }
- else
- {
- window_destroy(hWnd);
- }
- return 0;
-
- case WM_PAINT:
- PaintWindow(hWnd, pw);
- return 0;
-
- case WM_SETFOCUS:
- SetFocus(pw->hEdit);
- return 0;
-
- case WM_LBUTTONDOWN:
- MouseDown(hWnd, pw, LOWORD(lParam), HIWORD(lParam));
- break;
-
- case WM_MOUSEMOVE:
- if (pw->bHaveMouse)
- MouseMove(hWnd, pw, LOWORD(lParam), HIWORD(lParam));
- break;
-
- case WM_LBUTTONUP:
- if (pw->bHaveMouse)
- MouseUp(pw);
- break;
-
- case WM_VSCROLL:
- Scroll(hWnd, pw, wParam, LOWORD(lParam));
- break;
-
- case WM_SYSCOMMAND:
- switch(wParam)
- {
- case SC_COPY:
- CopyText(hWnd, pw);
- break;
-
- case SC_PASTE:
- PasteText(hWnd, pw);
- break;
-
- case SC_COPYPASTE:
- if (CopyText(hWnd, pw))
- PasteText(hWnd, pw);
- break;
- }
- break;
-
- case ENTER_HIT:
- GotLine(pw);
- break;
-
- case UP_HIT:
- if (pw->pw_history)
- {
- if (pw->pw_history->plPrev)
- {
- pw->pw_history = pw->pw_history->plPrev;
- }
- else
- {
- MessageBeep(MB_ICONEXCLAMATION);
- break;
- }
- }
- else if (pw->pw_histail)
- {
- pw->pw_history = pw->pw_histail;
- }
- else
- {
- MessageBeep(MB_ICONEXCLAMATION);
- break;
- }
- SetWindowText(pw->hEdit, pw->pw_history->pchLine);
- break;
-
- case DOWN_HIT:
- if (pw->pw_history)
- {
- if (pw->pw_history->plNext)
- {
- pw->pw_history = pw->pw_history->plNext;
- }
- else
- {
- MessageBeep(MB_ICONEXCLAMATION);
- break;
- }
- }
- else if (pw->pw_hishead)
- {
- pw->pw_history = pw->pw_hishead;
- }
- else
- {
- MessageBeep(MB_ICONEXCLAMATION);
- break;
- }
- SetWindowText(pw->hEdit, pw->pw_history->pchLine);
- break;
- }
- return DefWindowProc(hWnd, wMsg, wParam, lParam);
- }
-
-
-
- #pragma argsused
- int
- window_open( char const *pchPath,
- int iMode,
- int iAccess)
- {
- HWND hWnd;
- HMENU hmenuSys;
-
- if (!bRegistered)
- {
- WNDCLASS wc;
-
- wc.style = CS_GLOBALCLASS |
- CS_HREDRAW |
- CS_VREDRAW;
- wc.lpfnWndProc = WindowProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = sizeof(struct per_window *);
- wc.hInstance = hInstance;
- wc.hIcon = LoadIcon(hInstance, "TKERN_ICO");
- wc.hCursor = (HCURSOR) IDC_IBEAM;
- wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
- wc.lpszMenuName = 0;
- wc.lpszClassName = "Troy's Kernel Window";
- RegisterClass(&wc);
-
- iDevice = get_device_number("window");
- }
-
- hWnd = CreateWindow( "Troy's Kernel Window",
- pchPath,
- WS_VISIBLE | WS_OVERLAPPEDWINDOW | WS_VSCROLL,
- CW_USEDEFAULT,
- 0,
- CW_USEDEFAULT,
- 0,
- 0,
- 0,
- hInstance,
- 0
- );
- if (!hWnd)
- {
- nError = ENOMEM;
- return -1;
- }
- else
- {
- LockManager();
- hmenuSys = GetSystemMenu(hWnd, FALSE);
- AppendMenu(hmenuSys, MF_SEPARATOR, 0, 0);
- AppendMenu(hmenuSys, MF_STRING, SC_COPY, "C&opy");
- AppendMenu(hmenuSys, MF_STRING, SC_PASTE, "&Paste");
- AppendMenu(hmenuSys, MF_STRING, SC_COPYPASTE, "Cop&y and Paste");
- EnableMenuItem(hmenuSys, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
- ShowWindow(hWnd, SW_SHOW);
- return (int) hWnd;
- }
- }
-
- static void
- add_to_line( struct line *pl,
- char const *pchBuffer,
- int nBytes)
- {
- char *pchString;
-
- if (!nBytes)
- return;
- pchString = (char *) malloc(nBytes +
- (pl->pchLine ? strlen(pl->pchLine) : 0) + 1);
- if (pl->pchLine)
- strcpy(pchString, pl->pchLine);
- else
- *pchString = 0;
- pchString[strlen(pchString) + nBytes] = 0;
- memcpy(pchString + strlen(pchString), pchBuffer, nBytes);
- if (pl->pchLine)
- free(pl->pchLine);
- pl->pchLine = pchString;
- }
-
-
- int
- window_write( int id,
- char const *pchBuffer,
- int nBytes)
- {
- HWND hWnd = (HWND) id;
- struct per_window *pw = (struct per_window *) GetWindowLong(hWnd, 0);
- int nLines = 0;
- char *pchNewLine;
- char const *c = pchBuffer;
- struct line *plTemp;
- int nLeft = nBytes;
- RECT rcRedraw;
-
- if (!nBytes)
- return 0;
-
- while (nLeft--)
- {
- if (*c++ == '\n')
- {
- add_to_line(pw->pw_tail, pchBuffer, c - pchBuffer - 1);
- plTemp = (struct line *) malloc(sizeof(struct line));
- plTemp->pchLine = 0;
- plTemp->plNext = 0;
- plTemp->plPrev = pw->pw_tail;
- pw->pw_tail->plNext = plTemp;
- pw->pw_tail = plTemp;
- pchBuffer = c;
- nLines++;
- }
- }
- if (c != pchBuffer)
- add_to_line(pw->pw_tail, pchBuffer, c - pchBuffer);
- GetClientRect(hWnd, &rcRedraw);
- rcRedraw.top = rcRedraw.bottom - pw->cyChar - pw->cyChar / 5 * 2;
- InvalidateRect(hWnd, &rcRedraw, TRUE);
- if (nLines)
- {
- /* Rather than scrolling every line, which
- * is somewhat slow, scroll after some
- * number of lines as set by the user.
- * This is processed via a posted message,
- * so once an app starts flushing messages,
- * any outstanding scrolling should be
- * processed.
- */
- if (!pw->nScrollPos)
- {
- pw->nUnscrolledLines += nLines;
- if (pw->nUnscrolledLines >= pw->nScrollLines)
- FlushMessages();
- }
- MoveMark(pw, nLines);
- pw->nLines += nLines;
- while (pw->nLines > pw->nLinesMax)
- {
- plTemp = pw->pw_head;
- pw->pw_head = plTemp->plNext;
- if (plTemp->pchLine)
- free(plTemp->pchLine);
- free(plTemp);
- pw->pw_head->plPrev = 0;
- pw->nLines--;
- }
- if (pw->nScrollPos)
- pw->nScrollPos += nLines;
- SetScrollRange(hWnd, SB_VERT, 0, pw->nLines, FALSE);
- SetScrollPos(hWnd, SB_VERT, pw->nLines - pw->nScrollPos, TRUE);
- }
- return nBytes;
- }
-
- int
- window_read( int id,
- char *pchBuffer,
- int nBytes)
- {
- HWND hWnd = (HWND) id;
- struct per_window *pw = (struct per_window *) GetWindowLong(hWnd, 0);
- struct line *pl;
- char *pchNewLine;
- int iLen;
-
- if (!pw->pw_inhead)
- return FR_NOTREADY;
-
- pl = pw->pw_inhead;
-
- iLen = strlen(pl->pchLine);
- if (iLen >= nBytes)
- {
- memcpy(pchBuffer, pl->pchLine, nBytes);
- pchNewLine = (char *) malloc(iLen + 1 - nBytes);
- memcpy(pchNewLine, pl->pchLine + nBytes, iLen + 1 - nBytes);
- free(pl->pchLine);
- pl->pchLine = pchNewLine;
- }
- else
- {
- memcpy(pchBuffer, pl->pchLine, iLen);
- pchBuffer[iLen] = '\n';
- pw->pw_inhead = pl->plNext;
- if (!pl->plNext)
- pw->pw_intail = 0;
- free(pl->pchLine);
- free(pl);
- nBytes = iLen + 1;
- }
- window_write(id, pchBuffer, nBytes);
- return nBytes;
- }
-
- int
- window_close( int id)
- {
- HWND hWnd = (HWND) id;
- struct per_window *pw = (struct per_window *) GetWindowLong(hWnd, 0);
- HMENU hmenuSys = GetSystemMenu(hWnd, TRUE);
- char *pchOldText;
- char *pchNewText;
- int nTextLen;
-
- EnableMenuItem(hmenuSys, SC_CLOSE, MF_BYCOMMAND | MF_ENABLED);
- pw->bProgramClosed = TRUE;
- nTextLen = GetWindowTextLength(hWnd);
- pchOldText = (char *) malloc(nTextLen + 1);
- GetWindowText(hWnd, pchOldText, nTextLen + 1);
- pchOldText[nTextLen] = 0;
- pchNewText = malloc(nTextLen + 12);
- strcpy(pchNewText, "(Inactive ");
- strcat(pchNewText, pchOldText);
- strcat(pchNewText, ")");
- free(pchOldText);
- SetWindowText(hWnd, pchNewText);
- free(pchNewText);
- return 0;
- }
-
- static int
- window_destroy(HWND hWnd)
- {
- struct line *pl, *plNext;
- struct per_window *pw = (struct per_window *) GetWindowLong(hWnd, 0);
-
- DestroyWindow(hWnd);
- for (pl = pw->pw_head; pl; pl = plNext)
- {
- plNext = pl->plNext;
- if (pl->pchLine)
- free(pl->pchLine);
- free(pl);
- }
- for (pl = pw->pw_hishead; pl; pl = plNext)
- {
- plNext = pl->plNext;
- if (pl->pchLine)
- free(pl->pchLine);
- free(pl);
- }
- for (pl = pw->pw_inhead; pl; pl = plNext)
- {
- plNext = pl->plNext;
- if (pl->pchLine)
- free(pl->pchLine);
- free(pl);
- }
- free(pw);
- UnlockManager();
- return 0;
- }
-
- void
- CheckLimits( HWND hWnd,
- struct per_window *pw)
- {
- struct line *plTemp;
-
- while (pw->nLines > pw->nLinesMax)
- {
- plTemp = pw->pw_head;
- pw->pw_head = plTemp->plNext;
- if (plTemp->pchLine)
- free(plTemp->pchLine);
- free(plTemp);
- pw->pw_head->plPrev = 0;
- pw->nLines--;
- }
-
- while (pw->nHistory > pw->nHistMax)
- {
- plTemp = pw->pw_hishead;
- pw->pw_hishead = plTemp->plNext;
- pw->pw_hishead->plPrev = 0;
- if (plTemp->pchLine)
- free(plTemp->pchLine);
- free(plTemp);
- pw->nHistory--;
- }
- pw->pw_history = 0;
- SetScrollRange(hWnd, SB_VERT, 0, pw->nLines, FALSE);
- }
-
- void
- GetWindowSize( HWND hWnd,
- struct per_window *pw,
- struct winsize *wsize)
- {
- RECT rcWindow;
-
- GetClientRect(hWnd, &rcWindow);
- wsize->ws_xpixel = rcWindow.right;
- wsize->ws_ypixel = rcWindow.bottom;
- wsize->ws_col = rcWindow.right / pw->cxChar;
- wsize->ws_row = (rcWindow.bottom - pw->cyChar / 5 * 2) / pw->cyChar;
- }
-
- void
- SetWindowSize( HWND hWnd,
- struct per_window *pw,
- struct winsize *wsize)
- {
- RECT rcClient;
- RECT rcWindow;
- int xExtra;
- int yExtra;
- int xSize;
- int ySize;
-
- GetClientRect(hWnd, &rcClient);
- GetWindowRect(hWnd, &rcWindow);
- xExtra = (rcWindow.right - rcWindow.left) - rcClient.right;
- yExtra = (rcWindow.bottom - rcWindow.top) - rcClient.bottom;
-
- if (wsize->ws_col)
- xSize = wsize->ws_col * pw->cxChar;
- else if (wsize->ws_xpixel)
- xSize = wsize->ws_xpixel;
- else
- xSize = rcClient.right;
-
- if (wsize->ws_row)
- ySize = wsize->ws_row * pw->cyChar + pw->cyChar / 5 * 2;
- else if (wsize->ws_ypixel)
- ySize = wsize->ws_ypixel;
- else
- ySize = rcClient.bottom;
-
- MoveWindow(hWnd,
- rcWindow.left,
- rcWindow.top,
- xSize + xExtra,
- ySize + yExtra,
- TRUE);
- }
-
- int
- window_ioctl( int fd,
- struct tk_ioctl *tki)
- {
- HWND hWnd = (HWND) fd;
- struct wio_parms * const wiop = (struct wio_parms *) tki->achBuffer;
- struct per_window *pw = (struct per_window *) GetWindowLong(hWnd, 0);
-
- switch(tki->nIOCtl)
- {
- case WIOCGETHANDLE:
- return fd;
-
- case WIOCGETNAME:
- return GetWindowText(hWnd, tki->achBuffer, tki->nSize);
-
- case WIOCSETNAME:
- SetWindowText(hWnd, tki->achBuffer);
- return 0;
-
- case WIOCGETPARMS:
- wiop->wiop_display_lines = pw->nLinesMax;
- wiop->wiop_history_lines = pw->nHistMax;
- wiop->wiop_scroll_lines = pw->nScrollLines;
- return 0;
-
- case WIOCSETPARMS:
- pw->nLinesMax = wiop->wiop_display_lines;
- pw->nHistMax = wiop->wiop_history_lines;
- pw->nScrollLines = wiop->wiop_scroll_lines;
- CheckLimits(hWnd, pw);
- return 0;
-
- case TIOCGWINSZ:
- GetWindowSize(hWnd, pw, (struct winsize *) tki->achBuffer);
- return 0;
-
- case TIOCSWINSZ:
- SetWindowSize(hWnd, pw, (struct winsize *) tki->achBuffer);
- return 0;
-
- default:
- nError = EINVAL;
- return -1;
- }
- }