static bool loadNewAreas(void) { sMemArea *area,*end; void *oldEnd; /* allocate one page for area-structs */ oldEnd = chgsize(1); if(oldEnd == NULL) return false; if(pageCount == 0) heapstart = (uintptr_t)oldEnd; /* determine start- and end-address */ pageCount++; area = (sMemArea*)oldEnd; end = area + (PAGE_SIZE / sizeof(sMemArea)); /* put all areas in the freelist */ freeList = area; area->next = NULL; area++; while(area < end) { area->next = freeList; freeList = area; area++; } return true; }
static bool loadNewSpace(size_t size) { void *oldEnd; size_t count; sMemArea *area; /* no free areas? */ if(freeList == NULL) { if(!loadNewAreas()) return false; } /* check for overflow */ if(size + PAGE_SIZE < PAGE_SIZE) return false; /* allocate the required pages */ count = (size + PAGE_SIZE - 1) / PAGE_SIZE; oldEnd = chgsize(count); if(oldEnd == NULL) return false; if(pageCount == 0) heapstart = (uintptr_t)oldEnd; pageCount += count; /* take one area from the freelist and put the memory in it */ area = freeList; freeList = freeList->next; area->address = oldEnd; area->size = PAGE_SIZE * count; /* put area in the usable-list */ area->next = usableList; usableList = area; return true; }
/* This function creates a window */ static ELVBOOL vio_creategw (char *name, /* name of new window's buffer */ char *attributes) /* other window parameters, if any */ { VWIN *newp; /* if we don't have room for any more windows, then fail */ if (o_ttyrows / (nwindows + 1) < MINHEIGHT) { return ElvFalse; } /* create a window */ newp = safealloc (1, sizeof (VWIN)); /* initialize the window */ if (vwins) { newp->height = 0; newp->pos = o_ttyrows; } else { newp->height = o_ttyrows; newp->pos = 0; } newp->cursx = newp->cursy = 0; newp->shape = CURSOR_NONE; /* insert the new window into the list of windows */ newp->next = vwins; vwins = newp; nwindows++; /* adjust the heights of the other windows to make room for this one */ chgsize (newp, (int)(o_ttyrows / nwindows), ElvFalse); drawborder (newp); /* make elvis do its own initialization */ if (!eventcreate ((GUIWIN *)newp, NULL, name, newp->height, (int)o_ttycolumns)) { /* elvis can't make it -- fail */ safefree (newp); return ElvFalse; } /* make the new window be the current window */ current = newp; return ElvTrue; }
/* This function deletes a window */ static void vio_destroygw (GUIWIN *gw, /* window to be destroyed */ ELVBOOL force) /* if ElvTrue, try harder */ { VWIN *scan, *lag; /* delete the window from the list of windows */ for (lag = NULL, scan = vwins; scan != (VWIN *)gw; lag = scan, scan = scan->next) { } if (lag) { lag->next = scan->next; } else { vwins = scan->next; } /* if it was the current window, it isn't now */ if (scan == current) { current = vwins; } /* adjust the sizes of other windows (if any) */ nwindows--; if (nwindows > 0) { chgsize ((VWIN *)gw, 0, ElvFalse); } /* If this is the last window, move the cursor to the last line, and * erase it. If the buffer is going to be written, this is where the * "wrote..." message will appear. */ if (nwindows == 0) { vio_revert (NULL); vio_CM(o_ttyrows - 1, 0); vio_CE(vc_term); } /* simulate a "destroy" event */ eventdestroy (gw); /* free the storage */ safefree (gw); }
/* This function handles the visual <Tab> command */ static ELVBOOL vio_tabcmd (GUIWIN *gw, /* window that the command should affect */ _CHAR_ key2, /* second key of <Tab> command */ long count) /* argument of the <Tab> command */ { VWIN *vw = (GUIWIN *)gw; int newheight; int oldheight; int oldpos; /* if only one window, then we can't change its size */ if (nwindows == 1) return ElvFalse; /* remember the old position */ newheight = oldheight = vw->height; oldpos = vw->pos; switch (key2) { case '=': if (count >= MINHEIGHT) { newheight = count; break; } /* else fall through... */ case '+': newheight += (count ? count : 1); break; case '-': newheight -= (count ? count : 1); if (newheight < MINHEIGHT) { newheight = MINHEIGHT; } break; case '\\': newheight = o_ttyrows; /* will be reduced later */ break; default: return ElvFalse; } /* try to change the heights of other windows to make this one fit */ chgsize (vw, newheight, ElvFalse); newheight = vw->height; /* resize/expose this window */ if (newheight != oldheight) { drawborder (vw); eventresize (vw, vw->height, (int)o_ttycolumns); } else if (vw->pos != oldpos) { drawborder (vw); eventexpose (vw, 0, 0, newheight - 1, (int)(o_ttycolumns - 1)); } return ElvTrue; }
/* Repeatedly get events (keystrokes), and call elvis' event functions */ static void vio_loop (void) { char buf[20]; int len; int timeout = 0; MAPSTATE mst = MAP_CLEAR; VWIN *scan; /* perform the -c command or -t tag */ mainfirstcmd(windefault); while (vwins) { /* reset the ttycaught bitmap */ ttycaught = 0; /* if no window is current, then make the newest current */ if (!current) { current = vwins; } /* redraw the window(s) */ { /* redraw each window; the current one last */ for (scan = vwins; scan; scan = scan->next) { if (scan != current) { scan->shape = eventdraw ((GUIWIN *)scan); } } current->shape = eventdraw ((GUIWIN *)current); movecurs (current); /* make the cursor be this window's shape */ cursorshape (current->shape); } /* choose a timeout value */ switch (mst) { case MAP_CLEAR: timeout = 0; break; case MAP_USER: timeout = o_usertime; break; case MAP_KEY: timeout = o_keytime; break; } /* read events */ do_flush (); vio_CM (c_row, c_col); len = vio_read (buf, sizeof buf, timeout); /* process keystroke data */ if (len == -2) { /* vio_read() itself did something. We don't need to * do anything except the usual screen updates. */ } else if (len == -1) { /* Maybe the screen was resized? Get new size */ vio_getsize (); /* Resize the windows to match the new screen. The * easiest way to do this is to "change" the size of the * current window to its original size and force the * other windows to compensate. If there is only one * window, then should be resized to the screen size. */ chgsize (current, vwins->next ? current->height : (int)o_ttyrows, ElvTrue); } else { mst = eventkeys ((GUIWIN *)current, toCHAR (buf), len); /* if first keystroke after running an external * program, then we need to expose every window. */ if (afterprg == 1) { /* reset the flag BEFORE exposing windows, * or else the eventexpose() won't work right. */ afterprg = 0; vio_resume (ElvTrue); for (scan = vwins; scan; scan = scan->next) { eventexpose ((GUIWIN *)scan, 0, 0, scan->height - 1, (int)(o_ttycolumns - 1)); } } else if (afterprg == 2) { /* it became 2 while processing the earlier * keystrokes. Set it to 1 now, so we'll * read one more keystroke before exposing * all the windows. */ afterprg = 1; } } } }