home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************/
- /* File Id. Reorder.C. */
- /* Author. Stan Milam. */
- /* Date Written. 02/06/89. */
- /* */
- /* (c) Copyright 1989, 1990 by Stan Milam */
- /* */
- /* Comments: The functions in this file control & maintain*/
- /* a list of all windows being used. When a window is */
- /* pushed it is added to the list and occupies the first */
- /* position in the list. When a window is poped it is re- */
- /* moved from the list, hidden and deleted. If a window in*/
- /* the middle or end of the list is addressed that window */
- /* is floated to the top of the list recursively. The */
- /* variable, topwnd, always points to the beginning of the */
- /* list. */
- /***********************************************************/
-
- #if __TURBOC__ || __ZTC__
- # define _fmalloc farmalloc
- # define _ffree farfree
- # if __TURBOC__
- # include <alloc.h>
- # endif
- #else
- # include <malloc.h>
- #endif
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <dos.h>
- #include "pcw.i"
- #include "pcwproto.h"
-
- #define USER 1 /* User hidden attribute */
- #define SYSTEM 2 /* System hidden attribute */
-
- /* Function Prototypes of local functions */
-
- static int chk_wnds(WNDPTR *wnd);
- static int hide_wnd(WNDPTR *wnd, int attribute);
- static int show_wnd(WNDPTR *wnd, int attribute);
- static int wnd_overlap(WNDPTR *wnd1, WNDPTR *wnd2);
- static void level_wnds(WNDPTR *wnd);
- static void remove_from_list(WNDPTR *wnd);
- static void reshow_wnds(WNDPTR *wnd);
- static void insert_first_in_list(WNDPTR *wnd);
- static void change_wnd_position(WNDPTR *wnd,int row,int col,int cl,int rw);
-
- static WNDPTR *topwnd = (WNDPTR *) NULL;
-
- /************************************************************/
- /* Get_Active_Wnd */
- /* */
- /* Returns the most active (top) window. If no windows are */
- /* up returns NULL. */
- /************************************************************/
-
- WNDPTR *get_active_wnd(void) {
-
- return(topwnd);
- }
-
- /************************************************************/
- /* Wndmove */
- /* */
- /* This function will handle moving a window from one place */
- /* on the screen to another. It is placed in this file */
- /* because it needs close proximity to the hide/show func- */
- /* tions. */
- /************************************************************/
-
- int wndmove(WNDPTR *wnd, int row, int col) {
-
- int rw, cl;
-
- if (!chk_video_state(&rw,&cl)) return(0);
- if (wnd->hideflag == USER) { /* If hidden then */
- change_wnd_position(wnd,row,col,cl,rw); /* Change position */
- return(1); /* And return */
- }
- if (chk_wnds(wnd)) { /* Remove overlapping winds */
- hide_wnd(wnd, SYSTEM); /* Hide our wnd */
- reshow_wnds(wnd->back); /* Show overlaps */
- change_wnd_position(wnd,row,col,cl,rw); /* Change our position */
- show_wnd(wnd, SYSTEM); /* And Show it */
- }
- else {
- hide_wnd(wnd, SYSTEM); /* No overlaps so hide */
- change_wnd_position(wnd,row,col,cl,rw); /* Change position */
- show_wnd(wnd, SYSTEM); /* And show it */
- }
- remove_from_list(wnd); /* Move wnd to first */
- insert_first_in_list(wnd); /* In list */
- level_wnds(topwnd); /* Relevel all windows */
- return(1); /* Return */
- }
-
- /***********************************************************/
- /* Change_Wnd_Position */
- /* */
- /* This function calculates the new position of a window. */
- /* Checks that it will be in bounds of screen and adjusts */
- /* if it is not. */
- /***********************************************************/
-
- static void change_wnd_position(WNDPTR *wnd,int row,int col,int cl,int rw) {
-
- int rows, cols;
-
- rows = (wnd->lrow - wnd->urow); /* Calc total rows */
- cols = (wnd->lcol - wnd->ucol); /* Same for cols */
-
- if (row < 1) row = 1;
- if (col < 1) col = 1;
-
- if ((col + cols) > cl) { /* Is it in bounds */
- cl = (col + cols) - cl;
- col = col - cl;
- }
-
- if ((row + rows) > rw) { /* Is it in bounds? */
- rw = (row + rows) - rw; /* No - Adjust the rows */
- row= row - rw;
- }
-
- wnd->urow = row; /* Save in wnd structure */
- wnd->ucol = col;
- wnd->lrow = row + rows;
- wnd->lcol = col + cols;
- }
-
- /************************************************************/
- /* Re_Order */
- /* */
- /* This function is the main driver for the window list */
- /* management routines. Its job, depending on the action to*/
- /* be taken is to handle the logic of managing how the */
- /* windows are ordered visibly, and how they are ordered */
- /* logically in the window list. */
- /************************************************************/
-
- void re_order(WNDPTR *wnd, int action) {
-
- switch(action) {
- case NORMAL : /* Bring window to surface */
- if (wnd->level == 1) return; /* If first in list-forget it */
- if (chk_wnds(wnd)) { /* If window overlap then */
- hide_wnd(wnd, SYSTEM); /* Hide our window */
- reshow_wnds(wnd->back); /* Show those that were hid */
- show_wnd(wnd, SYSTEM); /* Put ours on top */
- }
- remove_from_list(wnd); /* Remove from window list */
- insert_first_in_list(wnd); /* Make it the logical first */
- break;
-
- case PUSH : /* Adding a new window to list */
- insert_first_in_list(wnd); /* Insert it first */
- break; /* Over & Out! */
-
- case POP : /* For pops */
- if (wnd->hideflag) { /* If window hidden */
- remove_from_list(wnd); /* Remove it from list */
- break; /* And get out */
- }
- if (wnd->level == 1) { /* If first in list */
- remove_from_list(wnd); /* Remove it */
- hide_wnd(wnd, SYSTEM); /* Hide it */
- }
- else {
- if (chk_wnds(wnd)) { /* If someone overlaps */
- hide_wnd(wnd, SYSTEM); /* Hide ours */
- reshow_wnds(wnd->back); /* Reshow other windows */
- }
- else hide_wnd(wnd, SYSTEM); /* No overlaps - so hide */
- remove_from_list(wnd); /* Remove from list */
- }
- break;
-
- case HIDE :
- if (wnd->level == 1) { /* If first window... */
- hide_wnd(wnd, USER); /* Hide it with user attribute */
- return; /* and return */
- }
- if (chk_wnds(wnd)) { /* Remove overlaps if any */
- hide_wnd(wnd, USER); /* Hide window with user attr */
- reshow_wnds(wnd->back); /* Reshow the overlaps */
- }
- else {
- hide_wnd(wnd, USER); /* No overlaps so just hide */
- return; /* Return */
- }
- break;
-
- case SHOW :
- if (wnd->hideflag != USER) /* Do not try to show a */
- return; /* Window not hidden */
- show_wnd(wnd, USER); /* Show the window */
- remove_from_list(wnd); /* Put the window first in */
- insert_first_in_list(wnd); /* List */
- break;
-
- }
- level_wnds(topwnd); /* Relevel the windows. */
- }
-
-
- /************************************************************/
- /* Remove_From_List */
- /* */
- /* This routine will remove a window from the window list. */
- /* The logic is most likely more complicated than needed but*/
- /* better safe than sorry when worrying about null pointer */
- /* assignments. */
- /************************************************************/
-
- static void remove_from_list(WNDPTR *wnd) {
-
- if (wnd->back == NULL) { /* Means its the top */
- if (wnd->next == NULL) /* Means its the only one */
- topwnd = (WNDPTR *) NULL; /* Set the top to NULL */
- else {
- wnd->next->back = (WNDPTR *) NULL; /* Set the back to NULL */
- topwnd = wnd->next; /* Make the next on top */
- }
- }
- else { /* Its in middle or at end */
- if (wnd->next == NULL) /* Its the end */
- wnd->back->next = (WNDPTR *) NULL; /* Cut it out of list */
- else { /* Its in the middle */
- wnd->next->back = wnd->back; /* Remove & reset all */
- wnd->back->next = wnd->next; /* the pointers */
- }
- }
- }
-
- /************************************************************/
- /* Insert_First_In_List */
- /* */
- /* The name says it all. A little logic to protect against */
- /* the dreaded "Null Pointer Assignment" message. */
- /************************************************************/
- static void insert_first_in_list(WNDPTR *wnd) {
-
- wnd->next = (WNDPTR *) topwnd; /* Insert it first in list */
- wnd->back = (WNDPTR *) NULL; /* Back always set to NULL */
- if (topwnd != NULL) /* If topwnd = NULL then */
- topwnd->back = wnd; /* NO assignment PLEASE */
- topwnd = wnd; /* Make our wnd first */
- }
-
- /*************************************************************/
- /* Chk_Wnds */
- /* */
- /* This routine recursively determines if a window is over- */
- /* lapping another. If a window is found to be overlapping */
- /* it must hide that window, but first it must determine if */
- /* a window above it is overlapping so it calls itself. */
- /* It will work its way down - and up - the list removing */
- /* all overlapping windows. */
- /*************************************************************/
-
- static int chk_wnds(WNDPTR *wnd) {
-
- WNDPTR *wrkwnd;
- int overlap;
-
- wrkwnd = topwnd; /* Start with top window */
- overlap= 0; /* Set local auto to false */
- while (wrkwnd->level < wnd->level) { /* While 1 less than level */
- if (!wrkwnd->hideflag) { /* If its hidden forget it */
- if (wnd_overlap(wrkwnd, wnd)) { /* If they overlap */
- overlap = 1; /* Set our switch */
- chk_wnds(wrkwnd); /* Recurse with new window */
- hide_wnd(wrkwnd, SYSTEM); /* Finally hide it */
- }
- }
- wrkwnd = wrkwnd->next; /* Grab next window */
- }
- return (overlap); /* Return our switch setting */
- }
-
- /************************************************************/
- /* Reshow_Wnds */
- /* */
- /* This function reshows any windows we had to hide along */
- /* the way. It runs thru the list backwards to the beginning*/
- /************************************************************/
-
- static void reshow_wnds(WNDPTR *wnd) {
-
- while (wnd) { /* Run Backwards thru the */
- if (wnd->hideflag != USER) /* If user attr skip */
- show_wnd(wnd, SYSTEM); /* List showing windows */
- wnd = wnd->back; /* We pulled off */
- }
- }
- /* */
- /************************************************************/
- /* Level_Wnds */
- /* */
- /* This funtion runs thru the list from the beginning and */
- /* reassignes level values to each window after and inser- */
- /* tion or deletion. */
- /************************************************************/
-
- static void level_wnds(WNDPTR *wnd) {
-
- int i = 1;
- WNDPTR *wrkwnd;
-
- wrkwnd = wnd;
- while (wrkwnd) { /* While window pointer not NULL */
- wrkwnd->level = i++; /* Assign a new level number */
- wrkwnd = wrkwnd->next; /* Get next window */
- }
- }
-
- /************************************************************/
- /* Hide_Wnd */
- /* */
- /* This routine will hide a specified window with one of two*/
- /* attributes, USER & SYSTEM. The system attribute means */
- /* the window system is hiding the window for its own */
- /* purposes and is a temporary hide while the user attribute*/
- /* means the user wanted to hide the window and leave it */
- /* hidden until it is desired to be shown. USER overrides */
- /* SYSTEM, meaning if the system is running thru the list */
- /* showing all SYSTEM hidden windows the USER hidden will */
- /* be ignored. */
- /************************************************************/
-
- static int hide_wnd(WNDPTR *wnd, int attribute) {
-
- int rows, cols, page, pagesize;
- unsigned offset, scrnseg;
- int far *scrnptr;
-
- if (wnd->hideflag) return(1); /* Can't hide again */
- if (wnd->wbuffer == (char far *) NULL)
- return(0);
-
- cols = (wnd->lcol - wnd->ucol) + 1; /* Calc total cols */
- rows = (wnd->lrow - wnd->urow) + 1; /* And rows */
- page = wnd->page;
-
- if (wnd->wsave == (char far *) NULL) {
- wnd->wsave = (char far *) _fmalloc((rows * cols) * 2);
- if (wnd->wsave == (char far *) NULL)
- return(0);
- }
-
- pagesize = getpagesize();
- scrnseg = getscrnseg();
- offset = MK_SCRNOFF(wnd->urow,wnd->ucol);
- scrnptr = (int far *) MK_FP(scrnseg, offset);
-
- SaveScrn(rows, cols, scrnptr, wnd->wsave);
- RestoreScrn(rows, cols, scrnptr, wnd->wbuffer);
- wnd->hideflag = attribute;
- return(1);
- }
-
- /************************************************************/
- /* Show_Wnd */
- /* */
- /* This function will show the windows that were hidden. */
- /* If the show is with attribute SYSTEM and the window was */
- /* hidden with USER we will bypass. */
- /************************************************************/
-
- static int show_wnd(WNDPTR *wnd, int attribute) {
-
- int rows, cols, page, pagesize;
- unsigned scrnseg, offset;
- int far *scrnptr;
-
- if (wnd->wbuffer == NULL || wnd->wsave == NULL) /* Exit if not */
- return(0); /* Ever allocated */
-
- if (wnd->hideflag != attribute) /* Can't show if */
- return(0); /* Attr don't match */
-
- wnd->hideflag = 0; /* Reset hideflag */
- rows = (wnd->lrow - wnd->urow) + 1; /* Calc total rows */
- cols = (wnd->lcol - wnd->ucol) + 1; /* And Cols */
- page = wnd->page; /* Get the scrn page */
-
- scrnseg = getscrnseg(); /* Get scrn segment */
- pagesize= getpagesize(); /* get pagesize */
- offset = MK_SCRNOFF(wnd->urow,wnd->ucol); /* Calc offset */
- scrnptr = (int far *) MK_FP(scrnseg, offset); /* Make a far pointer */
-
- SaveScrn(rows, cols, scrnptr, wnd->wbuffer); /* Save whats there */
- RestoreScrn(rows, cols, scrnptr, wnd->wsave); /* Put the wnd down */
- return(1); /* Return */
- }
-
-
- /************************************************************/
- /* Wnd_Overlap */
- /* */
- /* This routine determines if two windows overlap the same */
- /* portion of the screen. It is a bit difficult to tell how*/
- /* it works. I had to draw myself some pictures of over- */
- /* lapping windows to figure it out. */
- /************************************************************/
-
- static int wnd_overlap(WNDPTR *wnd1, WNDPTR *wnd2) {
-
- if (wnd1->page != wnd2->page) /* If not in same page */
- return(0); /* they can't overlap */
-
- if (((wnd2->ucol >= wnd1->ucol) && (wnd2->ucol <= wnd1->lcol)) &&
- (((wnd2->urow >= wnd1->urow) && (wnd2->urow <= wnd1->lrow)) ||
- ((wnd2->lrow >= wnd1->urow) && (wnd2->lrow <= wnd1->lrow))))
- return(1);
-
- if (((wnd2->lcol >= wnd1->ucol) && (wnd2->lcol <= wnd1->lcol)) &&
- (((wnd2->urow >= wnd1->urow) && (wnd2->urow <= wnd1->lrow)) ||
- ((wnd2->lrow >= wnd1->urow) && (wnd2->lrow <= wnd1->lrow))))
- return(1);
-
- if (((wnd1->ucol >= wnd2->ucol) && (wnd1->lcol <= wnd2->lcol)) &&
- (((wnd1->urow >= wnd2->urow) && (wnd1->urow <= wnd2->lrow)) ||
- ((wnd1->lrow >= wnd2->urow) && (wnd1->lrow <= wnd2->lrow))))
- return(1);
-
- if (((wnd1->urow >= wnd2->urow) && (wnd1->lrow <= wnd2->lrow)) &&
- (((wnd1->ucol >= wnd2->ucol) && (wnd1->ucol <= wnd2->lcol)) ||
- ((wnd1->lcol >= wnd2->ucol) && (wnd1->lcol <= wnd2->lcol))))
- return(1);
-
- if ((wnd1->ucol > wnd2->ucol && wnd1->lcol < wnd2->lcol) &&
- (wnd1->urow > wnd2->urow && wnd1->lrow < wnd2->lrow))
- return(1);
-
- return(0);
- }
-