/* $Id: ckmwin.c,v 1.2 91/12/27 21:51:47 fdc Exp $ * $Source: /uw/mackermit/RCS/ckmwin.c,v $ *------------------------------------------------------------------ * $Log: ckmwin.c,v $ * Revision 1.2 91/12/27 21:51:47 fdc * Change fatal to macfatal. * * Revision 1.1 91/10/30 23:06:06 rick * Initial revision * *------------------------------------------------------------------ * $Endlog$ */ /* * cmkwin.c * Common window handling routines for the command and remote * windows. * * R. Watson * The University of Texas * 12-Sep-1991 */ /* Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New York. Permission is granted to any individual or institution to use this software as long as it is not sold for profit. This copyright notice must be retained. This software may not be included in commercial products without written permission of Columbia University. */ #include "ckcdeb.h" #include "ckcasc.h" #include "ckcker.h" #include "ckmdef.h" /* General Mac defs */ #include "ckmres.h" /* Resource file defs */ #include "ckmwin.h" /* Window handling defs */ #include "ckmcon.h" #include "ckmptp.h" /* Prototypes */ #define LMARGIN 4 /* left margin in teviewr */ struct cmdw *cmdwl = NULL; /* list of TE windows */ struct cmdw *rcmdw = NULL; /* remote command window */ struct cmdw *prntw = NULL; /* local "printer" window */ struct cmdw *activecmdw = NULL; /* cmdw if window is active */ struct cmdw *docmdw; /* cmdw for rdoscroll() */ int cmdinterminal = FALSE; /* cmd output to term window if true */ extern MenuHandle menus[]; extern int connected; extern Boolean have_128roms; /* actually, a Mac + or better */ extern Cursor *textcurs, *normcurs, *watchcurs; /* mouse cursor shapes */ extern Cursor *lastCursor; /* what we set the cursor to last */ void cmdwSelectWindow (struct cmdw *cmdw); void updateTakeMenu (struct cmdw *cmdw); void setWindowLoc (int id); /* * initcmdw() * Initialize a TE based window. */ struct cmdw *initcmdw (id, vscroll, hscroll) int id; /* window id */ int vscroll; /* vertical scroll CTRL id */ int hscroll; /* horiz scroll CTRL id */ { struct cmdw *cmdw; GrafPtr savePort; static int ourid = 1; /* unique id of this cmdw */ GetPort (&savePort); /* save current port */ cmdw = (struct cmdw *)malloc(sizeof(struct cmdw)); if (!cmdw) macfatal("No memory for cmdw", 0); bzero((char *)cmdw, sizeof(struct cmdw)); cmdw->next = cmdwl; /* link on list */ cmdwl = cmdw; cmdw->id = ourid++; /* allocate unique id */ setWindowLoc(id); #ifdef notdef cmdw->window = GetNewWindow(id, (Ptr) &cmdw->WRec, (WindowPtr) 0L); #else cmdw->window = GetNewWindow(id, (Ptr) 0L, (WindowPtr) -1L); #endif SetPort (cmdw->window); /* set new stuff */ TextFont (monaco); TextSize (9); /* min and max are defined in the resource declaration */ cmdw->vscroll = GetNewControl(vscroll, cmdw->window); cmdw->hscroll = GetNewControl(hscroll, cmdw->window); sizescrollbars(cmdw); /* make controls adjust to wind size */ sizeteviewr(cmdw); /* resize text edit rect */ /* create text edit portion */ cmdw->teh = TENew (&cmdw->teviewr, &cmdw->teviewr); HLock((Handle)cmdw->teh); (*cmdw->teh)->crOnly = -1; /* only break lines at CR */ cmdw->theorigin.h = 0; cmdw->theorigin.v = 0; SetPort (savePort); /* restore previous port */ return cmdw; } /****************************************************************************/ /* sizescrollbars - called when window is created and after a window grow */ /* sequence to resize the scroll window's bars. */ /****************************************************************************/ sizescrollbars (cmdw) struct cmdw *cmdw; { register Rect *r; r = &cmdw->window->portRect; /* window size */ HideControl (cmdw->vscroll); HideControl (cmdw->hscroll); MoveControl (cmdw->vscroll, r->right - 15, r->top - 1); SizeControl (cmdw->vscroll, 16, r->bottom - r->top - 13); MoveControl (cmdw->hscroll, r->left - 1, r->bottom - 15); SizeControl (cmdw->hscroll, r->right - r->left - 13, 16); ShowControl (cmdw->vscroll); ShowControl (cmdw->hscroll); } /****************************************************************************/ /****************************************************************************/ sizeteviewr (cmdw) struct cmdw *cmdw; { cmdw->teviewr = cmdw->window->portRect; cmdw->teviewr.left = cmdw->teviewr.left + LMARGIN; cmdw->teviewr.right = cmdw->teviewr.right - 15; cmdw->teviewr.bottom = cmdw->teviewr.bottom - 15; } /****************************************************************************/ /****************************************************************************/ void growremwindow (cmdw, p) struct cmdw *cmdw; Point p; { long gr; int height; int width; Rect growRect; GrafPtr savePort; growRect = qd.screenBits.bounds; growRect.top = 50; /* minimal horizontal size */ growRect.left = 50; /* minimal vertical size */ gr = GrowWindow (cmdw->window, p, &growRect); if (gr == 0) return; height = HiWord (gr); width = LoWord (gr); SizeWindow (cmdw->window, width, height, FALSE); /* resize the window */ sizescrollbars(cmdw); /* size the scroll bars */ sizeteviewr(cmdw); /* size for text edit */ (*cmdw->teh)->viewRect = cmdw->teviewr; /* set it */ GetPort (&savePort); SetPort (cmdw->window); InvalRect (&cmdw->window->portRect);/* invalidate whole window rectangle */ SetPort (savePort); } /****************************************************************************/ /****************************************************************************/ rcmdwhide (cmdw) struct cmdw *cmdw; { HideWindow(cmdw->window); /* hide it */ HideControl(cmdw->vscroll); /* these will be shown on select */ HideControl(cmdw->hscroll); } /* * rrcmdwshow * Show the remote window. * Here so ckuus4.c doesn't need to know about window details. */ rrcmdwshow() { rcmdwshow(rcmdw); } /****************************************************************************/ /****************************************************************************/ rcmdwshow (cmdw) struct cmdw *cmdw; { ShowWindow (cmdw->window); /* show it */ cmdwSelectWindow (cmdw); } /****************************************************************************/ /* rcdactivate - activate event on rcd window */ /****************************************************************************/ rcdactivate (cmdw, mod) struct cmdw *cmdw; int mod; { DrawGrowIcon(cmdw->window); if (mod & activeFlag) { TEFromScrap(); TEActivate(cmdw->teh); ShowControl (cmdw->vscroll); ShowControl (cmdw->hscroll); DisableItem(menus[EDIT_MENU], UNDO_EDIT); updateTakeMenu(cmdw); activecmdw = cmdw; } else { ZeroScrap(); TEToScrap(); TEDeactivate(cmdw->teh); HideControl(cmdw->vscroll); HideControl(cmdw->hscroll); EnableItem(menus[EDIT_MENU], UNDO_EDIT); activecmdw = NULL; } } /****************************************************************************/ /****************************************************************************/ pascal void rdoscroll (WHICHCONTROL, THECODE) ControlHandle WHICHCONTROL; short THECODE; { register int amount = 0, val, max; if (THECODE == inUpButton) amount = -1; if (THECODE == inDownButton) amount = 1; if (amount == 0) return; val = GetCtlValue (WHICHCONTROL) + amount; max = GetCtlMax (WHICHCONTROL); if ((val < 0) || (val > max)) return; SetCtlValue (WHICHCONTROL, GetCtlValue (WHICHCONTROL) + amount); scrollbits(docmdw); } /* rdoscroll */ /****************************************************************************/ /* rcdkey - key event on rcd window */ /****************************************************************************/ rcdkey (cmdw, evt) struct cmdw *cmdw; EventRecord *evt; { int i, y; int nl; /* num lines in window */ unsigned char the_char; TEPtr ptr; Point pt; the_char = evt->message & charCodeMask; TEKey(the_char, cmdw->teh); cmdw->flags |= CMDWF_MODIFIED; /* buffer is modified */ if (the_char == '\n') /* if extending number of lines */ setscrollmax(cmdw); /* * Find location of insertion point. * TODO: Do this for horizontal locations also. Will need to * use TextWidth() I think. */ ptr = *cmdw->teh; for (i = ptr->nLines; i >= 0; i--) /* set i to line number */ if (ptr->selEnd >= ptr->lineStarts[i]) break; y = (i - GetCtlValue(cmdw->vscroll)) * ptr->lineHeight; pt.h = LMARGIN; pt.v = y + ptr->lineHeight/2; nl = ((ptr->viewRect.bottom-ptr->viewRect.top) / ptr->lineHeight); if (!PtInRect(pt, &cmdw->teviewr)) { if (pt.v > cmdw->teviewr.bottom) { /* if past bottom */ SetCtlValue(cmdw->vscroll, i-nl+1); scrollbits(cmdw); } else { /* must be above top */ SetCtlValue(cmdw->vscroll, i); scrollbits(cmdw); } } } /****************************************************************************/ /* rcdmouse - mouse event on rcd window */ /****************************************************************************/ rcdmouse (cmdw, evt) struct cmdw *cmdw; EventRecord *evt; { int actrlcode; int t; ControlHandle acontrol; GrafPtr savePort; GetPort (&savePort); /* save the current port */ SetPort (cmdw->window); GlobalToLocal (&evt->where);/* convert to local */ if (PtInRect (evt->where, &cmdw->teviewr)) { /* in text edit? */ TEClick(evt->where, (evt->modifiers) & shiftKey, cmdw->teh); SetPort (savePort); /* restore previous port */ return; /* yes, do nothing */ } actrlcode = FindControl (evt->where, cmdw->window, &acontrol); switch (actrlcode) { case inUpButton: case inDownButton: docmdw = cmdw; /* save pointer for rdoscroll */ t = TrackControl (acontrol, evt->where, (ProcPtr) rdoscroll); break; case inPageUp: pagescroll (cmdw, actrlcode, -10, acontrol); break; case inPageDown: pagescroll (cmdw, actrlcode, 10, acontrol); break; case inThumb: t = TrackControl (acontrol, evt->where, (ProcPtr) NIL); scrollbits(cmdw); break; } SetPort (savePort); /* restore previous port */ } /* rcdmouse */ rcd_cut(cmdw) struct cmdw *cmdw; { invalidate_scr_clip(); TECut(cmdw->teh); } rcd_copy(cmdw) struct cmdw *cmdw; { invalidate_scr_clip(); TECopy(cmdw->teh); } rcd_paste(cmdw) struct cmdw *cmdw; { /* * If the internal clip is newer, it will have been already copied to the * global clip, so this will just work. */ TEPaste(cmdw->teh); } rcd_clear(cmdw) struct cmdw *cmdw; { TEDelete(cmdw->teh); } /****************************************************************************/ /****************************************************************************/ rcdupdate (cmdw) struct cmdw *cmdw; { EraseRect(&cmdw->teviewr); TEUpdate(&cmdw->teviewr, cmdw->teh); DrawGrowIcon(cmdw->window); DrawControls(cmdw->window); } /****************************************************************************/ /****************************************************************************/ scrollbits (cmdw) struct cmdw *cmdw; { Point oldorigin; int dh, dv; oldorigin = cmdw->theorigin; cmdw->theorigin.h = GetCtlValue(cmdw->hscroll); cmdw->theorigin.v = GetCtlValue(cmdw->vscroll); dh = (oldorigin.h - cmdw->theorigin.h); dv = (oldorigin.v - cmdw->theorigin.v) * (*cmdw->teh)->lineHeight; TEScroll (dh, dv, cmdw->teh); } /****************************************************************************/ /****************************************************************************/ rcdwscroll (cmdw) struct cmdw *cmdw; { GrafPtr savePort; GetPort (&savePort); SetPort (cmdw->window); /* our window is the port */ setscrollmax (cmdw); /* set the max */ SetCtlValue (cmdw->vscroll, GetCtlMax (cmdw->vscroll)); /* & set control */ scrollbits(cmdw); /* do scroll */ SetPort (savePort); /* back to old port */ } /****************************************************************************/ /****************************************************************************/ pagescroll (cmdw, code, amount, ctrlh) struct cmdw *cmdw; ControlHandle ctrlh; { Point myPt; do { GetMouse (&myPt); if (TestControl (ctrlh, myPt) != code) continue; SetCtlValue (ctrlh, GetCtlValue (ctrlh) + amount); scrollbits(cmdw); } while (StillDown ()); } /****************************************************************************/ /* setscrollmax - sets the vertical scroll control's maximum value. * The max is the total number of lines in the te record * minus the number of lines that can be displayed in the * viewing rectangle (plus 1). This makes the max setting * of the control result in the display of the last chunk * of text. */ /****************************************************************************/ int setscrollmax (cmdw) struct cmdw *cmdw; { int maxv; maxv = (*cmdw->teh)->nLines + 1 - (((*cmdw->teh)->viewRect.bottom-(*cmdw->teh)->viewRect.top) / (*cmdw->teh)->lineHeight); if (maxv < 0) /* for less than one page */ maxv = 0; /* use this value as max */ SetCtlMax (cmdw->vscroll, maxv); /* set it... */ return maxv; } /* setscrollmax */ /****************************************************************************/ /* PWP: trimcon(length) should be called before TEInsert()ing */ /* number of bytes. This function checks to see if there is enough */ /* room for this many characters, and deletes a bit from the beginning */ /* if there isn't space. */ /* Returns 1 if it trimmed, 0 if it didn't. */ /****************************************************************************/ int trimcon(cmdw, l) struct cmdw *cmdw; register int l; { if (cmdw) { if (((*cmdw->teh)->teLength + l) > TE_TOOBIG) { TESetSelect(0, TE_TRIM, cmdw->teh);/* select beginning part */ TEDelete(cmdw->teh); /* nuke it */ /* and make insertion point at end again */ TESetSelect(TE_MAX, TE_MAX, cmdw->teh); return (1); } } return (0); } /* * cmdwbywindow * Find a cmdw given a WindowPtr */ struct cmdw *cmdwbywindow (WindowPtr w) { struct cmdw *cmdw; cmdw = cmdwl; while (cmdw) { if (cmdw->window == w) break; cmdw = cmdw->next; } return(cmdw); } /* * termwbywindow * Find a termw given a WindowPtr */ struct termw *termwbywindow (WindowPtr w) { struct termw *termw; extern struct termw *termwl; termw = termwl; while (termw) { if (termw->window == w) break; termw = termw->next; } return(termw); } /* * cmdwSelectWindow */ void cmdwSelectWindow (struct cmdw *cmdw) { SelectWindow(cmdw->window); updateTakeMenu(cmdw); } /* * updateTakeMenu */ void updateTakeMenu (struct cmdw *cmdw) { char scratch[255]; /* * If this is a file window, update and enable the Take * Command from Window menu item. Otherwise, disable * the item. */ if (cmdw->flags & CMDWF_FILE) { if (have_128roms) { sprintf(scratch, "Take \"%s\"", p2c_tmp(cmdw->wname)); c2pstr(scratch); DelMenuItem(menus[FILE_MENU], TAKEW_FIL); InsMenuItem(menus[FILE_MENU], scratch, TAKEW_FIL-1); } EnableItem(menus[FILE_MENU], TAKEW_FIL); } else { DisableItem(menus[FILE_MENU], TAKEW_FIL); } } /* * kSelectWindow */ VOID kSelectWindow (WindowPtr w) { SelectWindow(w); /* * Selecting the terminal window or the command window implicitly * connects or disconnects us. */ if (ttermw->window == w) connected = TRUE; else if (ctermw->window == w) connected = FALSE; DisableItem(menus[FILE_MENU], TAKEW_FIL); } /* * kShowWindow * Only call ShowWindow if window is not showing. */ VOID kShowWindow (struct termw *termw) { if (termw->showing) return; ShowWindow(termw->window); termw->showing = TRUE; } /* * kHideWindow * Only call HideWindow if window is showing. */ VOID kHideWindow (struct termw *termw) { if (!termw->showing) return; HideWindow(termw->window); termw->showing = FALSE; } /* * setWindowLoc * Set initial location of a window we're about to create. */ #define TCORNER 40 /* corner of first window */ #define LCORNER 5 #define TINC 15 /* how far to move each window */ #define LINC 10 void setWindowLoc (int id) { int ldiff, tdiff; Handle wh; /* window handle */ Rect *rectp; static int tcorner = TCORNER; /* window (top, left) corner */ static int lcorner = LCORNER; static int n = 0; /* * Wrap window location after so many windows. */ if (++n > 9) { n = 0; tcorner = TCORNER + TINC; /* don't re-use first slot */ lcorner = LCORNER + LINC; } /* * Get the window resource and modify the location. * Since it will already be in memory, GetNewWindow will use * the values we just set. */ wh = GetResource('WIND', id); rectp = (Rect *)*wh; ldiff = lcorner - rectp->left; tdiff = tcorner - rectp->top; rectp->top = tcorner; rectp->left = lcorner; rectp->bottom = rectp->bottom + tdiff; rectp->right = rectp->right + ldiff; tcorner += TINC; lcorner += LINC; } /* * cmdwUpdateCursor * Update cursor when a cmdw window is the front window. */ void cmdwUpdateCursor (struct cmdw *cmdw) { Point MousePt; GrafPtr savePort; Cursor *curs; GetPort (&savePort); SetPort (cmdw->window); GetMouse(&MousePt); if (PtInRect(MousePt, &cmdw->teviewr)) curs = textcurs; else curs = normcurs; if (lastCursor!= curs) { SetCursor(curs); lastCursor = curs; } }