/* The routines in this file provide extra emacs functions available under the Microsoft Windows environment on an IBM-PC or compatible computer. The following functions are supplied: cutregion, clipregion, insertclip and helpengine. Also implemented here is the support for scroll bars Must be compiled with Borland C++ 2.0 or MSC 6.0 or later versions It should not be compiled if the WINDOW_MSWIN symbol is not set */ #include "estruct.h" #include #include "eproto.h" #include "edef.h" #include "elang.h" #include "mswin.h" #include "mswmenu.h" /* to invoke the commands corresponding to scroll bar actions */ #define MAXSCROLL 32767 /* maximum position for scrollbars */ static HANDLE hClipData = NULL; /* used by insertclip and ClipboardCleanup */ /* CopyToClipboard: internal function to copy region to clipboard */ /* =============== */ static BOOL PASCAL CopyToClipboard (REGION *Region) { long Size = 0L; HANDLE hData; #if WINDOW_MSWIN32 char *Data; #else char huge *Data; #endif BOOL Result = TRUE; register LINE *lp; register int Offset; register int lcnt; /* used to reduce longop() overhead */ /*-figure out the size of the clipboard data (end of lines have to be turned into CR-LF) */ Size = Region->r_size; if (curwp->w_dotp != curwp->w_markp[0]) { /* multiple lines */ lp = Region->r_linep; do { ++Size; lp = lforw(lp); } while ((lp != curwp->w_dotp) && (lp != curwp->w_markp[0])); } if (Size == 0L) return TRUE; /*-copy the buffer data into a block of global memory */ if (hData = GlobalAlloc (GMEM_MOVEABLE, Size + 1)) { if (!(Data = GlobalLock (hData))) goto NoClipboardMemory; lp = Region->r_linep; Offset = Region->r_offset; lcnt = 0; while (Size-- > 0) { if (Offset != lused(lp)) { /* middle of line */ *Data++ = lgetc(lp, Offset); ++Offset; } else { /* end of line */ *Data++ = '\r'; *Data++ = '\n'; Size--; lp = lforw(lp); Offset = 0; if (--lcnt < 0) { longop (TRUE); lcnt = 10; /* reduce longop calls overhead */ } } } *Data = '\0'; /*-pass the text to the clipboard */ GlobalUnlock (hData); if (OpenClipboard (hFrameWnd)) { if (EmptyClipboard ()) { SetClipboardData (CF_TEXT, hData); } else Result = FALSE; CloseClipboard (); } else Result = FALSE; if (Result == FALSE) GlobalFree (hData); } else { NoClipboardMemory: mlabort (TEXT94); /* out of memory */ Result = FALSE; } return Result; } /* CopyToClipboard */ /* cutregion: move the current region to the clipboard */ /* ========= */ int PASCAL cutregion (int f, int n) { REGION Region; int Result; /*-don't allow command if read-only mode */ if (curbp->b_mode & MDVIEW) return rdonly(); if ((Result = getregion (&Region)) != TRUE) return Result; if ((Result = CopyToClipboard (&Region)) != TRUE) return Result; curwp->w_dotp = Region.r_linep; curwp->w_doto = Region.r_offset; return ldelete (Region.r_size, FALSE); } /* cutregion */ /* clipregion: copy the current region into the clipboard */ /* ========== */ int PASCAL clipregion (int f, int n) { REGION Region; int Result; if ((Result = getregion (&Region)) != TRUE) return Result; return CopyToClipboard (&Region); } /* clipregion */ /* insertclip: insert the clipboard contents at dot */ /* ========== */ int PASCAL insertclip (int f, int n) { BOOL Result = TRUE; char *Text, *TextHead; short int curoff; LINE *curline; /*-don't allow command if read-only mode */ if (curbp->b_mode & MDVIEW) return rdonly(); if (OpenClipboard (hFrameWnd)) { if ((hClipData = GetClipboardData (CF_TEXT)) != NULL) { /* Save the local pointers to hold global "." */ if (yankflag) { /* Find the *previous* line, since the line we are on may disappear due to re-allocation. This works even if we are on the first line of the file. */ curline = lback(curwp->w_dotp); curoff = curwp->w_doto; } if ((TextHead = GlobalLock (hClipData)) != NULL) { while (n--) { Text = TextHead; while (*Text != '\0') { if (*Text == '\n') { if (lnewline () == FALSE) { Result = FALSE; goto bail_out; } } else { if (*Text != '\r') if (linsert (1, *Text) == FALSE) { Result = FALSE; goto bail_out; } } ++Text; } } bail_out: GlobalUnlock (hClipData); hClipData = NULL; /* for ClipboardCleanup */ /* If requested, set global "." back to the beginning of the yanked text. */ if (yankflag) { curwp->w_dotp = lforw(curline); curwp->w_doto = curoff; } } } else Result = FALSE; CloseClipboard (); } else Result = FALSE; return Result; } /* insertclip */ /* ClipboardCleanup: to be called if the user aborts during a longop */ /* ================ */ void FAR PASCAL ClipboardCleanup (void) { if (hClipData) { GlobalUnlock (hClipData); CloseClipboard (); } } /* ClipboardCleanup */ /* helpengine: invoke the MS-Windows help engine */ /* ========== */ int PASCAL helpengine (int f, int n) { char OldHelpFile [NFILEN]; char HelpKey [NLINE]; BOOL Result; strcpy (OldHelpFile, HelpEngineFile); SetWorkingDir (); if ((Result = FILENAMEREPLY (TEXT307, HelpEngineFile, NFILEN)) != TRUE) return Result; /* "Help file: " */ if (HelpEngineFile[0] == '\0') { strcpy (HelpEngineFile, OldHelpFile); return FALSE; } else { Result = mlreply (TEXT308, HelpKey, NLINE); if ((Result != TRUE) && (Result != FALSE)) return Result; /* "Help key: " */ if (HelpKey[0] == '\0') { WinHelp (hFrameWnd, HelpEngineFile, HELP_INDEX, NULL); } else { WinHelp (hFrameWnd, HelpEngineFile, HELP_KEY, (DWORD)(LPSTR)&HelpKey[0]); } } return TRUE; } /* helpengine */ /* minimizescreen: turn the current screen into an icon */ /* ============== */ PASCAL minimizescreen (int f, int n) { BOOL nq; nq = notquiescent; notquiescent = 0; ShowWindow (first_screen->s_drvhandle, SW_MINIMIZE); notquiescent = nq; return TRUE; } /* minimizescreen */ /* ForceMessage: do a SendMessage, forcing quiescent mode */ /* ============ */ static PASCAL ForceMessage (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { BOOL nq; nq = notquiescent; notquiescent = 0; SendMessage (hWnd, wMsg, wParam, lParam); notquiescent = nq; } /* ForceMessage */ /* maximizescreen: maximize the current screen */ /* ============== */ PASCAL maximizescreen (int f, int n) { ForceMessage (hMDIClientWnd, WM_MDIMAXIMIZE, (UINT)first_screen->s_drvhandle, 0L); return TRUE; } /* maximizescreen */ /* restorescreen: restore the current screen from maximized/minimized state */ /* ============= */ PASCAL restorescreen (int f, int n) { ForceMessage (hMDIClientWnd, WM_MDIRESTORE, (UINT)first_screen->s_drvhandle, 0L); return TRUE; } /* restorescreen */ /* tilescreens: tile the non-iconized screens */ /* =========== */ PASCAL tilescreens (int f, int n) /* without a numeric argument, tile horizontally. With a numeric argument of 1, tile vertically */ { if (f && (n == 1)) { ForceMessage (hMDIClientWnd, WM_MDITILE, MDITILE_HORIZONTAL, 0L); } else ForceMessage (hMDIClientWnd, WM_MDITILE, MDITILE_VERTICAL, 0L); return TRUE; } /* tilescreens */ /* cascadescreens: position the non-iconized screens in cascade */ /* ============== */ PASCAL cascadescreens (int f, int n) { ForceMessage (hMDIClientWnd, WM_MDICASCADE, 0, 0L); return TRUE; } /* cascadescreens */ /* ScrollMessage: handle WM_HSCROLL and WM_VSCROLL */ /* ============= */ void FAR PASCAL ScrollMessage (HWND hWnd, UINT wMsg, WORD ScrlCode, int Pos) { int Delta; if (notquiescent) return; if (wMsg == WM_VSCROLL) { switch (ScrlCode) { case SB_LINEUP: mvupwind (FALSE, 1); break; case SB_LINEDOWN: mvdnwind (FALSE, 1); break; case SB_PAGEUP: backpage (FALSE, 1); break; case SB_PAGEDOWN: forwpage (FALSE, 1); break; case SB_THUMBTRACK: case SB_THUMBPOSITION: if (Win31API) { if (ScrlCode == SB_THUMBPOSITION) return; } else { if (ScrlCode == SB_THUMBTRACK) return; /* there is something wrong with thumb tracking in Windows 3.0 */ } Delta = Pos - GetScrollPos (hWnd, SB_VERT); if (Delta) mvdnwind (TRUE, Delta); break; default: return; } curwp->w_flag |= WFMODE; } else { switch (ScrlCode) { case SB_LINEUP: Delta = -1; break; case SB_LINEDOWN: Delta = 1; break; case SB_PAGEUP: Delta = -term.t_ncol; break; case SB_PAGEDOWN: Delta = term.t_ncol; break; case SB_THUMBTRACK: Delta = Pos - GetScrollPos (hWnd, SB_HORZ); break; default: return; } curwp->w_fcol += Delta; if (curwp->w_fcol < 0) curwp->w_fcol = 0; if (curwp->w_doto < curwp->w_fcol) { /* reframe dot if it was left past the left of the screen */ curwp->w_doto = min(curwp->w_fcol,lused(curwp->w_dotp)); } if (curwp->w_doto > (curwp->w_fcol + term.t_ncol - 2)) { /* reframe dot if it was left past the right of the screen */ curwp->w_doto = curwp->w_fcol + term.t_ncol - 2; } curwp->w_flag |= WFMODE | WFHARD; } if (in_check()) GenerateMenuSeq (IDM_NULLPROC); /* this ensures we go through the editloop(), updating the modeline display and running the cmdhook, among other things */ ShowEmacsCaret (FALSE); update (TRUE); ShowEmacsCaret (TRUE); } /* ScrollMessage */ /* ScrollBars: shows/hides, enables/disables scroll bars for all screens */ /* ========== */ void FAR PASCAL ScrollBars (void) { static int VScroll = TRUE; static int HScroll = TRUE; static int Enabled = TRUE; int Quiescence; SCREEN *sp; if (vscrollbar) vscrollbar = TRUE; /* normalize... */ if (hscrollbar) hscrollbar = TRUE; Quiescence = (notquiescent == 0); for (sp = first_screen; sp != (SCREEN*)NULL; sp = sp->s_next_screen) { if (vscrollbar != VScroll) { ShowScrollBar ((HWND)sp->s_drvhandle, SB_VERT, vscrollbar); } if (hscrollbar != HScroll) { ShowScrollBar ((HWND)sp->s_drvhandle, SB_HORZ, hscrollbar); } if ((Enabled != Quiescence) && Win31API && !TakingANap) { /* note: no disabling of scroll bars during naps (i.e. fence matching), to avoid annoying blinking */ EnableScrollBar ((HWND)sp->s_drvhandle, SB_BOTH, Quiescence ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH); } } if ((Enabled != Quiescence) && Win31API && !TakingANap) { Enabled = Quiescence; } VScroll = vscrollbar; HScroll = hscrollbar; } /* ScrollBars */ /* updscrollbars: updates the scroll bars for a screen */ /* ============= */ PASCAL updscrollbars (SCREEN *sp, char w_flag) /* the w_flag is used to determine what needs updating: if the WFHARD bit is set, both scroll bars need an update. If the WFMOVE bit is set, the horizontal scroll bar needs an update */ /* this function assumes s_cur_window matches curwp for the first_screen */ { int ScrollMax, ScrollMin, ScrollPos; if (vscrollbar && (w_flag & WFHARD)) { int lastline; int topline; { /*-figure-out where we are at vertically */ register LINE *lp; register LINE *linep; /* header (= last) line of buffer */ LINE *toplp; /* top line of window */ linep = sp->s_cur_window->w_bufp->b_linep; toplp = sp->s_cur_window->w_linep; topline = lastline = 0; lp = linep; do { lp = lforw(lp); lastline++; if (lp == toplp) topline = lastline; } while (lp != linep); } lastline += 1 - sp->s_cur_window->w_ntrows; if (lastline <= 1) lastline = 2; /* to avoid scrollbar hiding */ lastline = min(lastline, MAXSCROLL); topline = min(topline, MAXSCROLL); GetScrollRange ((HWND)sp->s_drvhandle, SB_VERT, &ScrollMin, &ScrollMax); if ((ScrollMax != lastline) || (ScrollMin != 1)) { SetScrollRange ((HWND)sp->s_drvhandle, SB_VERT, 1, lastline, FALSE); ScrollPos = -1; /* makes sure the scroll display is updated */ } else ScrollPos = GetScrollPos ((HWND)sp->s_drvhandle, SB_VERT); if (topline != ScrollPos) { SetScrollPos ((HWND)sp->s_drvhandle, SB_VERT, topline, TRUE); } } if (hscrollbar && (w_flag & (WFMOVE | WFHARD))) { /*-figure-out where we stand horizontally */ int row; LINE *lp; EWINDOW *wp = sp->s_cur_window; int maxlength = 0; lp = wp->w_linep; for (row = 0; (row < wp->w_ntrows) && (lp != wp->w_bufp->b_linep); row++) { maxlength = max(maxlength, lused(lp)); lp = lforw(lp); } if (maxlength <= 0) maxlength = 1; maxlength = min(maxlength, MAXSCROLL); row = min(wp->w_fcol, MAXSCROLL); GetScrollRange ((HWND)sp->s_drvhandle, SB_HORZ, &ScrollMin, &ScrollMax); if ((ScrollMax != maxlength) || (ScrollMin != 0)) { SetScrollRange ((HWND)sp->s_drvhandle, SB_HORZ, 0, maxlength, FALSE); ScrollPos = -1; /* makes sure the scroll display is updated */ } else ScrollPos = GetScrollPos ((HWND)sp->s_drvhandle, SB_HORZ); if (row != ScrollPos) { SetScrollPos ((HWND)sp->s_drvhandle, SB_HORZ, row, TRUE); } } } /* updscrollbars */