home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari FTP
/
ATARI_FTP_0693.zip
/
ATARI_FTP_0693
/
Mint
/
toswinsc.zoo
/
window.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-10-27
|
15KB
|
757 lines
/*
* Copyright 1992 Eric R. Smith. All rights reserved.
* Redistribution is permitted only if the distribution
* is not for profit, and only if all documentation
* (including, in particular, the file "copying")
* is included in the distribution in unmodified form.
* THIS PROGRAM COMES WITH ABSOLUTELY NO WARRANTY, NOT
* EVEN THE IMPLIED WARRANTIES OF MERCHANTIBILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. USE AT YOUR OWN
* RISK.
*/
#include <stdlib.h>
#include <gemfast.h>
#include <aesbind.h>
#include <vdibind.h>
#include <osbind.h>
#include <string.h>
#include "xgem.h"
#define WF_BEVENT 24
#define IM_RESERVE 12345
#define IM_RELEASE 12346
/*
* global variables
*/
/* current top window */
WINDOW *gl_topwin;
extern WINDOW *focuswin;
/* list of all windows in system */
WINDOW *gl_winlist;
/* do we want graf_{grow,shrink}box effects? */
int win_flourishes = 1;
/*
* some dummy functions for windows
*/
static void
clear_win(v, x, y, w, h)
WINDOW *v;
int x,y,w,h;
{
int temp[4];
vsf_color(vdi_handle, 0);
temp[0] = x;
temp[1] = y;
temp[2] = x + w - 1;
temp[3] = y + h - 1;
v_bar(vdi_handle, temp);
vsf_color(vdi_handle, 1);
}
static void
top_win(w)
WINDOW *w;
{
gl_topwin = w;
wind_set(w->wi_handle, WF_TOP, 0, 0, 0, 0);
}
static void
close_win(w)
WINDOW *w;
{
destroy_window(w);
}
static void
full_win(v)
WINDOW *v;
{
int newx, newy, neww, newh;
if (v->flags & WFULLED) {
wind_get(v->wi_handle, WF_PREVXYWH, &newx, &newy, &neww,
&newh);
} else {
wind_get(v->wi_handle, WF_FULLXYWH, &newx, &newy, &neww,
&newh);
}
wind_set(v->wi_handle, WF_CURRXYWH, newx, newy, neww, newh);
wind_get(v->wi_handle, WF_WORKXYWH, &v->wi_x, &v->wi_y, &v->wi_w,
&v->wi_h);
v->flags ^= WFULLED;
}
static void
move_win(v, x, y, w, h)
WINDOW *v;
int x, y, w, h;
{
int fullx, fully, fullw, fullh;
wind_get(v->wi_handle, WF_FULLXYWH, &fullx, &fully, &fullw, &fullh);
if (w > fullw) w = fullw;
if (h > fullh) h = fullh;
if (w != fullw || h != fullh)
v->flags &= ~WFULLED;
wind_set(v->wi_handle, WF_CURRXYWH, x, y, w, h);
wind_get(v->wi_handle, WF_WORKXYWH, &v->wi_x, &v->wi_y,
&v->wi_w, &v->wi_h);
}
static void
size_win(v, x, y, w, h)
WINDOW *v;
int x, y, w, h;
{
move_win(v, x, y, w, h);
}
static void
noslid(w, m)
WINDOW *w;
int m;
{
}
static int
nokey(w, code)
WINDOW *w;
int code;
{
return 0;
}
static int
nomouse(w, clicks, x, y, shift, mbuttons)
WINDOW *w;
int clicks, x, y, shift, mbuttons;
{
return 0;
}
static int
iconmouse(v, clicks, x, y, shift, mbuttons)
WINDOW *v;
int clicks, x, y, shift, mbuttons;
{
int w, h;
if (mbuttons) {
/* wait for a little bit */
evnt_timer(140L);
graf_mkstate(&x, &y, &mbuttons, &shift);
if (x < v->wi_x || x > v->wi_x + v->wi_w || y < v->wi_y ||
y > v->wi_y + v->wi_w)
return 1;
if (mbuttons) { /* button still down */
wind_update(BEG_MCTRL);
graf_mouse(FLAT_HAND, 0L);
wind_get(v->wi_handle, WF_CURRXYWH, &x, &y, &w, &h);
graf_dragbox(w, h, x, y, xdesk, ydesk, wdesk, hdesk,
&x, &y);
graf_mouse(ARROW, 0L);
wind_update(END_MCTRL);
(*v->moved)(v, x, y, w, h);
return 1;
}
}
(*v->fulled)(v); /* un-iconify the window */
return 1;
}
/* turn a window into an icon */
static void
uniconify_win(v)
WINDOW *v;
{
static int mbuf[8];
int newx, newy, neww, newh;
int id = appl_find("ICONMGR ");
if (!(v->flags & WICONIFIED)) return;
if (id >= 0) {
mbuf[0] = IM_RELEASE;
mbuf[1] = gl_apid;
mbuf[2] = 0;
mbuf[3] = v->icon_slot;
appl_write(id, 16, mbuf);
}
v->fulled = v->oldfulled;
v->mouseinp = v->oldmouse;
v->flags &= ~WICONIFIED;
if (win_flourishes) {
graf_growbox(v->wi_x, v->wi_y, v->wi_w, v->wi_h,
v->prevx, v->prevy, v->prevw, v->prevh);
}
wind_calc(WC_BORDER, v->old_wkind, v->prevx, v->prevy, v->prevw,
v->prevh, &newx, &newy, &neww, &newh);
change_window_gadgets(v, v->old_wkind);
(*v->sized)(v, newx, newy, neww, newh);
/* button events should top the window */
wind_set(v->wi_handle, WF_BEVENT, 0x0000, 0, 0, 0);
(*v->topped)(v);
}
static void
iconify_win(v, slot, x, y, w, h)
WINDOW *v;
int slot, x, y, w, h;
{
if (v->flags & WICONIFIED)
return;
v->flags &= ~WFULLED;
v->flags |= WICONIFIED;
v->oldfulled = v->fulled;
v->oldmouse = v->mouseinp;
v->icon_slot = slot;
v->old_wkind = v->wi_kind;
v->prevx = v->wi_x;
v->prevy = v->wi_y;
v->prevw = v->wi_w;
v->prevh = v->wi_h;
change_window_gadgets(v, 0);
if (win_flourishes) {
graf_shrinkbox(x, y, w, h, v->prevx, v->prevy, v->prevw,
v->prevh);
}
(*v->sized)(v, x, y, w, h);
/* we don't want the window topped inadvertently */
wind_set(v->wi_handle, WF_BEVENT, 0x0001, 0, 0, 0);
v->fulled = uniconify_win;
v->mouseinp = iconmouse;
new_topwin(1);
}
/*
* Create a new window with title "title," initial/full size x, y, w, h,
* and gadgets given by "kind." Returns a pointer to the new window,
* or NULL if an error occurs. The window is not actually opened,
* however.
*/
/* used to "stagger" opening positions of windows */
#define WOFF_INC gl_hbox
#define WOFF_MAX 64
static int winoff = 0;
WINDOW *
create_window(title, kind, wx, wy, ww, wh)
const char *title;
int kind, wx, wy, ww, wh;
{
WINDOW *v;
int fullx, fully, fullw, fullh;
int centerwin = 0;
if (title) {
title = strdup(title);
}
v = malloc(sizeof(WINDOW));
if (!v) return v;
v->wi_handle = -1; /* not open yet */
v->wi_kind = kind;
if (wx == 0 && wy == 0) centerwin = 1;
if (wx < xdesk) wx = xdesk;
if (wy < ydesk) wy = ydesk;
/* calculate max. window size needed for a working area of ww x wh */
wind_calc(WC_WORK, v->wi_kind, wx, wy, wdesk, hdesk,
&v->wi_x, &v->wi_y, &v->wi_w, &v->wi_h);
wind_calc(WC_BORDER, v->wi_kind, v->wi_x, v->wi_y, ww, wh,
&fullx, &fully, &fullw, &fullh);
if (fullw > wdesk)
fullw = wdesk;
if (fullh > hdesk)
fullh = hdesk;
if (centerwin) {
fullx = xdesk;
fully = ydesk;
}
fullx += winoff;
fully += winoff;
winoff += WOFF_INC;
if (winoff > WOFF_MAX) {
winoff = 0;
}
v->wi_title = (char *)title;
v->wi_fullx = fullx;
v->wi_fully = fully;
v->wi_fullw = fullw;
v->wi_fullh = fullh;
wind_calc(WC_WORK, v->wi_kind, fullx, fully, fullw, fullh,
&v->wi_x, &v->wi_y, &v->wi_w, &v->wi_h);
v->wtype = GENERIC_WIN;
v->extra = (void *)0;
v->icon_slot = -1;
v->flags = 0;
v->draw = clear_win;
v->topped = top_win;
v->closed = close_win;
v->fulled = full_win;
v->sized = size_win;
v->moved = move_win;
v->arrowed = noslid;
v->hslid = noslid;
v->vslid = noslid;
v->keyinp = nokey;
v->mouseinp = nomouse;
v->iconify = iconify_win;
v->oldfulled = v->fulled;
v->oldmouse = nomouse;
v->menu = 0;
v->infostr = 0;
v->next = gl_winlist;
gl_winlist = v;
return v;
}
WINDOW *
open_window(v)
WINDOW *v;
{
int wx, wy, ww, wh;
if (v->wi_handle >= 0) /* already open?? */
return v;
v->wi_handle = wind_create(v->wi_kind, v->wi_fullx, v->wi_fully,
v->wi_fullw, v->wi_fullh);
if (v->wi_handle < 0)
return 0;
wind_set(v->wi_handle, WF_BEVENT, 0x0000, 0, 0, 0);
if (v->wi_kind & NAME) {
if (v->wi_title)
wind_set(v->wi_handle, WF_NAME, v->wi_title);
else
wind_set(v->wi_handle, WF_NAME, "Untitled");
}
if (v->wi_kind & INFO) {
if (v->infostr) {
wind_set(v->wi_handle, WF_INFO, v->infostr);
} else {
wind_set(v->wi_handle, WF_INFO, "");
}
}
wind_calc(WC_BORDER, v->wi_kind, v->wi_x, v->wi_y, v->wi_w, v->wi_h,
&wx, &wy, &ww, &wh);
if (win_flourishes)
graf_growbox(wx + ww/2, wy + wh/2, gl_wbox ,gl_hbox,
wx, wy, ww, wh);
wind_open(v->wi_handle, wx, wy, ww, wh);
(*v->topped)(v);
/* set scroll bars, etc. correctly */
(*v->sized)(v, wx, wy, ww, wh);
return v;
}
void
close_window(v)
WINDOW *v;
{
int i, dummy;
if (v->wi_handle < 0) /* already closed? */
return;
wind_close(v->wi_handle);
if (win_flourishes)
graf_shrinkbox(v->wi_x + v->wi_w/2, v->wi_y + v->wi_h/2,
gl_wbox, gl_hbox, v->wi_x, v->wi_y, v->wi_w, v->wi_h);
wind_delete(v->wi_handle);
v->wi_handle = -1;
/* reset gl_topwin */
gl_topwin = 0;
wind_get(0, WF_TOP, &i, &dummy, &dummy, &dummy);
for (v = gl_winlist; v; v = v->next) {
if (v->wi_handle == i)
break;
}
if (v && !(v->flags & WICONIFIED))
(*v->topped)(v);
}
/*
* destroy a window
*/
void
destroy_window(v)
WINDOW *v;
{
WINDOW **ptr, *w;
extern void unloadmenu();
if (v->wi_handle >= 0) {
close_window(v);
}
if (v->wi_title)
free(v->wi_title);
if (v->infostr)
free(v->infostr);
/* find v in the window list, and unlink it */
ptr = &gl_winlist;
w = *ptr;
while (w) {
if (w == v) {
*ptr = v->next;
break;
}
ptr = &w->next;
w = *ptr;
}
/* maybe we should have an error here if v isn't found */
free(v);
}
/*
* redraw all parts of a window that lie within the rectangle
* xc, yc, wc, hc
*/
void
redraw_window(v, xc, yc, wc, hc)
WINDOW *v;
int xc, yc, wc, hc;
{
GRECT t1, t2;
int temp[4];
wind_update(TRUE);
hide_mouse();
t2.g_x = xc;
t2.g_y = yc;
t2.g_w = wc;
t2.g_h = hc;
wind_get(v->wi_handle, WF_FIRSTXYWH,
&t1.g_x, &t1.g_y, &t1.g_w, &t1.g_h);
while (t1.g_w && t1.g_h) {
if (rc_intersect(&t2, &t1)) {
temp[0] = t1.g_x;
temp[1] = t1.g_y;
temp[2] = temp[0]+t1.g_w-1;
temp[3] = temp[1]+t1.g_h-1;
vs_clip(vdi_handle, 1, temp);
(*v->draw)(v, t1.g_x, t1.g_y, t1.g_w, t1.g_h);
}
wind_get(v->wi_handle, WF_NEXTXYWH, &t1.g_x, &t1.g_y,
&t1.g_w, &t1.g_h);
}
show_mouse();
wind_update(FALSE);
}
/*
* find a window
*/
WINDOW *
which_window(x)
int x;
{
WINDOW *w;
if (x < 0) return 0;
for (w = gl_winlist; w; w = w->next)
if (w->wi_handle == x)
return w;
return 0;
}
/*
* handle an evnt_multi message dealing with windows
*/
void
handle_window(msgbuff)
int *msgbuff;
{
WINDOW *v;
v = which_window(msgbuff[3]);
if (!v) { /* hmmm, not our window? */
return;
}
switch(msgbuff[0]) {
case WM_REDRAW:
redraw_window(v, msgbuff[4], msgbuff[5], msgbuff[6], msgbuff[7]);
break;
case WM_TOPPED:
(*v->topped)(v);
break;
case WM_SIZED:
(*v->sized)(v, msgbuff[4], msgbuff[5], msgbuff[6], msgbuff[7]);
break;
case WM_MOVED:
(*v->moved)(v, msgbuff[4], msgbuff[5], msgbuff[6], msgbuff[7]);
break;
case WM_FULLED:
(*v->fulled)(v);
break;
case WM_ARROWED:
(*v->arrowed)(v, msgbuff[4]);
break;
case WM_HSLID:
(*v->hslid)(v, msgbuff[4]);
break;
case WM_VSLID:
(*v->vslid)(v, msgbuff[4]);
break;
case WM_CLOSED:
(*v->closed)(v);
break;
}
}
int
window_key(keycode, shift)
int keycode, shift;
{
MENU *m;
ENTRY *e;
WINDOW *w;
w = focuswin; /* set in evnt_loop */
if (w) {
/* first, check for window specific menu shortcut keys */
for (m = w->menu; m; m = m->next) {
for (e = m->contents; e; e = e->next) {
if (e->keycode == keycode) {
(*e->func)(e->arg);
return 1;
}
}
}
/* otherwise, pass the key along to the general window handling thing */
return (*w->keyinp)(w, keycode, shift);
}
else
return 0;
}
int
window_click(clicks, x, y, kshift, mbutton)
int clicks, x, y, kshift, mbutton;
{
WINDOW *w;
/* find the window that got clicked in (if any) */
w = find_window(x, y);
if (w) {
return (*w->mouseinp)(w, clicks, x, y, kshift, mbutton);
}
return 0;
}
/*
* close and delete all windows
*/
void
end_windows()
{
WINDOW *v;
v = gl_winlist;
while (v) {
gl_winlist = v->next;
if (v->wi_handle >= 0) {
wind_close(v->wi_handle);
wind_delete(v->wi_handle);
}
free(v);
v = gl_winlist;
}
}
/*
* force a redraw of a whole window
*/
void
force_redraw(v)
WINDOW *v;
{
redraw_window(v, v->wi_x, v->wi_y, v->wi_w, v->wi_h);
if (v->wtype == TEXT_WIN)
mark_clean(v->extra);
}
/*
* find out which window lies under the point (x,y). Returns a pointer
* to the window, or NULL
*/
WINDOW *
find_window(x, y)
int x, y;
{
int wx, wy, ww, wh;
WINDOW *w;
wind_update(1); /* lock the screen -- we don't want it changing */
for (w = gl_winlist; w; w = w->next) {
if (w->wi_handle < 0) continue;
wind_get(w->wi_handle, WF_FIRSTXYWH, &wx, &wy, &ww, &wh);
while (ww && wh) {
if (x >= wx && x <= wx + ww &&
y >= wy && y <= wy + wh)
goto found_window;
wind_get(w->wi_handle, WF_NEXTXYWH, &wx, &wy, &ww, &wh);
}
}
found_window:
wind_update(0);
return w; /* w will be null if no window found */
}
void
change_window_gadgets(w, newkind)
WINDOW *w;
int newkind;
{
int reopen = 0;
int nx, ny, nw, nh;
int oldflourishes;
if (newkind == w->wi_kind) return; /* no change */
oldflourishes = win_flourishes;
win_flourishes = 0;
if (w->wi_handle >= 0) {
wind_close(w->wi_handle);
wind_delete(w->wi_handle);
w->wi_handle = -1;
reopen = 1;
}
wind_calc(WC_WORK, w->wi_kind, w->wi_fullx, w->wi_fully, w->wi_fullw,
w->wi_fullh, &nx, &ny, &nw, &nh);
wind_calc(WC_BORDER, newkind, nx, ny, nw, nh, &nx,
&ny, &w->wi_fullw, &w->wi_fullh);
if (w->wi_fullw > wdesk)
w->wi_fullw = wdesk;
if (w->wi_fullh > hdesk)
w->wi_fullh = hdesk;
if (w->wi_fullx < xdesk)
w->wi_fullx = xdesk;
if (w->wi_fully < ydesk)
w->wi_fully = ydesk;
wind_calc(WC_BORDER, w->wi_kind, w->wi_x, w->wi_y, w->wi_w, w->wi_h,
&nx, &ny, &nw, &nh);
if (nw > w->wi_fullw)
nw = w->wi_fullw;
if (nh > w->wi_fullh)
nh = w->wi_fullh;
wind_calc(WC_WORK, newkind, nx, ny, nw, nh, &w->wi_x, &w->wi_y,
&w->wi_w, &w->wi_h);
w->wi_kind = newkind;
if (reopen) {
open_window(w);
}
win_flourishes = oldflourishes;
}
/*
* new_topwin: reset the top window so that it doesn't match the current
* top window (if that's possible). If force == 0, then we allow the current
* window to remain on top, otherwise we pretend that no window is on
* top
*/
void
new_topwin(force)
int force;
{
WINDOW *w;
int mbuf[8];
w = gl_topwin;
if (!w) return;
for(;;) {
w = w->next;
if (!w) w = gl_winlist;
if (w->wi_handle >= 0 && !(w->flags & WICONIFIED)) break;
if (w == gl_topwin) break;
}
if (w != gl_topwin) {
mbuf[0] = WM_TOPPED;
mbuf[1] = gl_apid;
mbuf[2] = 0;
mbuf[3] = w->wi_handle;
mbuf[4] = mbuf[5] = mbuf[6] = mbuf[7] = 0;
appl_write(gl_apid, 16, mbuf);
} else if (force) {
gl_topwin = 0;
}
}
/* set a window title */
void
title_window(w, title)
WINDOW *w; char *title;
{
if (w->wi_title)
free(w->wi_title);
w->wi_title = strdup(title);
if (w->wi_handle >= 0 && (w->wi_kind & NAME)) {
wind_set(w->wi_handle, WF_NAME, w->wi_title);
}
}