Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/src/editscreen.c')
-rw-r--r--source/blender/src/editscreen.c2931
1 files changed, 2931 insertions, 0 deletions
diff --git a/source/blender/src/editscreen.c b/source/blender/src/editscreen.c
new file mode 100644
index 00000000000..d71ae8c8e3d
--- /dev/null
+++ b/source/blender/src/editscreen.c
@@ -0,0 +1,2931 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * All screen functions that are related to the interface
+ * handling and drawing. Might be split up as well later...
+ */
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "nla.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "PIL_time.h"
+
+#include "BMF_Api.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "DNA_action_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BLO_writefile.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_blender.h"
+#include "BKE_screen.h"
+
+#include "BIF_editsound.h"
+#include "BIF_glutil.h"
+#include "BIF_gl.h"
+#include "BIF_graphics.h"
+#include "BIF_interface.h"
+#include "BIF_mainqueue.h"
+#include "BIF_mywindow.h"
+#include "BIF_renderwin.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "BIF_toets.h"
+#include "BIF_toolbox.h"
+#include "BIF_usiblender.h"
+#include "BIF_keyval.h"
+
+#include "BSE_edit.h"
+#include "BSE_filesel.h"
+#include "BSE_headerbuttons.h"
+#include "BSE_view.h"
+
+#include "license_key.h"
+#include "interface.h"
+#include "mydevice.h"
+#include "blendef.h"
+#include "render.h"
+
+#include "winlay.h"
+
+/* TIPS:
+ *
+ * - LET OP DE EDGES, VERTICES ERVAN MOETEN IN VOLGORDE
+ (laagste pointer eerst). Anders onvoorspelbare effecten!
+ * - probleem: flags zijn nog niet echt netjes. Altijd na gebruik
+ op nul zetten.
+ */
+
+static void testareas(void);
+static void area_autoplayscreen(void);
+static void wait_for_event(void);
+
+/* ********* Globals *********** */
+
+static Window *mainwin= NULL;
+static int prefsizx= 0, prefsizy= 0, prefstax= 0, prefstay= 0, start_maximized= 1;
+static short dodrawscreen= 0;
+static ScrArea *areawinar[MAXWIN];
+static ScrArea *g_activearea= NULL;
+short winqueue_break= 0;
+ScrArea *curarea= 0;
+
+/**********************************************************************/
+
+static void screen_set_cursor(bScreen *sc)
+{
+ if (sc->winakt>3) {
+ ScrArea *sa= areawinar[sc->winakt];
+
+ set_cursor(sa->cursor);
+ } else {
+ set_cursor(CURSOR_STD);
+ }
+}
+
+void waitcursor(int val)
+{
+ if(val) {
+ set_cursor(CURSOR_WAIT);
+ } else {
+ screen_set_cursor(G.curscreen);
+ }
+}
+
+static int choose_cursor(ScrArea *sa)
+{
+ if (sa->spacetype==SPACE_VIEW3D) {
+ if(G.obedit) return CURSOR_EDIT;
+ else if(G.f & G_VERTEXPAINT) return CURSOR_VPAINT;
+ else if(G.f & G_WEIGHTPAINT) return CURSOR_VPAINT;
+ else if(G.f & G_FACESELECT) return CURSOR_FACESEL;
+ else return CURSOR_STD;
+ } else {
+ return CURSOR_STD;
+ }
+}
+
+void wich_cursor(ScrArea *sa)
+{
+ sa->cursor= choose_cursor(sa);
+
+ screen_set_cursor(G.curscreen);
+}
+
+
+void setcursor_space(int spacetype, short cur)
+{
+ bScreen *sc;
+ ScrArea *sa;
+
+ for (sc= G.main->screen.first; sc; sc= sc->id.next)
+ for (sa= sc->areabase.first; sa; sa= sa->next)
+ if(sa->spacetype==spacetype)
+ sa->cursor= cur;
+
+ screen_set_cursor(G.curscreen);
+}
+
+
+/* ********* IN/OUT ************* */
+
+void getmouseco_sc(short *mval) /* screen coordinaten */
+{
+ getmouse(mval);
+}
+
+void getmouseco_areawin(short *mval) /* interne area coordinaten */
+{
+ getmouseco_sc(mval);
+
+ if(g_activearea && g_activearea->win) {
+ mval[0]-= g_activearea->winrct.xmin;
+ mval[1]-= g_activearea->winrct.ymin;
+ }
+}
+
+void getmouseco_headwin(short *mval) /* interne area coordinaten */
+{
+ getmouseco_sc(mval);
+
+ if(g_activearea && g_activearea->headwin) {
+ mval[0]-= g_activearea->headrct.xmin;
+ mval[1]-= g_activearea->headrct.ymin;
+ }
+}
+
+/* *********** STUFF ************** */
+
+static int scredge_is_horizontal(ScrEdge *se)
+{
+ return (se->v1->vec.y == se->v2->vec.y);
+}
+
+static ScrEdge *screen_find_active_scredge(bScreen *sc, short *mval)
+{
+ ScrEdge *se;
+
+ for (se= sc->edgebase.first; se; se= se->next) {
+ if (scredge_is_horizontal(se)) {
+ if (abs(mval[1]-se->v1->vec.y)<=EDGEWIDTH2 &&
+ abs(mval[0]-se->v1->vec.x)<=abs(se->v2->vec.x-se->v1->vec.x))
+ return se;
+ } else {
+ if (abs(mval[0]-se->v1->vec.x)<=EDGEWIDTH2 &&
+ abs(mval[1]-se->v1->vec.y)<=abs(se->v2->vec.y-se->v1->vec.y))
+ return se;
+ }
+ }
+
+ return NULL;
+}
+
+void areawinset(short win)
+{
+ if(win>3) {
+ curarea= areawinar[win];
+ if(curarea==0) {
+ printf("error in areawinar %d ,areawinset\n", win);
+ return;
+ }
+
+ switch(curarea->spacetype) {
+ case SPACE_VIEW3D:
+ G.vd= curarea->spacedata.first;
+ break;
+ case SPACE_IPO:
+ if(G.sipo != curarea->spacedata.first) allqueue(REDRAWBUTSANIM, 0);
+ G.sipo= curarea->spacedata.first;
+ G.v2d= &G.sipo->v2d;
+ break;
+ case SPACE_BUTS:
+ G.buts= curarea->spacedata.first;
+ G.v2d= &G.buts->v2d;
+ break;
+ case SPACE_SEQ: {
+ SpaceSeq *sseq= curarea->spacedata.first;
+ G.v2d= &sseq->v2d;
+ break;
+ }
+ case SPACE_OOPS:
+ G.soops= curarea->spacedata.first;
+ G.v2d= &G.soops->v2d;
+ break;
+ case SPACE_IMAGE:
+ G.sima= curarea->spacedata.first;
+ G.v2d= &G.sima->v2d;
+ case SPACE_SOUND:
+ G.ssound= curarea->spacedata.first;
+ G.v2d= &G.ssound->v2d;
+ break;
+ case SPACE_ACTION:
+ G.saction= curarea->spacedata.first;
+ G.v2d= &G.saction->v2d;
+ break;
+ case SPACE_NLA:
+ G.snla= curarea->spacedata.first;
+ G.v2d= &G.snla->v2d;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if(win) mywinset(win);
+}
+
+void headerbox(int selcol, int width)
+{
+ if(selcol) glClearColor(.75, .75, .75, 0.0);
+ else glClearColor(.65, .65, .65, 0.0);
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glColor3ub(0, 0, 0);
+ sdrawbox(0, 0, width, HEADERY);
+
+ glColor3ub(220, 220, 220);
+ sdrawline(0, HEADERY-1, width, HEADERY-1);
+
+ glColor3ub(176, 176, 176);
+ sdrawline(0, HEADERY-2, width, HEADERY-2);
+
+ glColor3ub(128, 128, 128);
+ sdrawline(0, 2, width, 2);
+
+ glColor3ub(64, 64, 64);
+ sdrawline(0, 1, width, 1);
+
+ glColor3ub(0, 0, 0);
+ sdrawline(0, 0, width, 0);
+}
+
+int area_is_active_area(ScrArea *area)
+{
+ return (g_activearea && area==g_activearea);
+}
+
+void scrarea_do_headdraw(ScrArea *area)
+{
+ areawinset(area->headwin);
+
+ headerbox(area_is_active_area(area), area->winx+100);
+
+ switch(area->spacetype) {
+ case SPACE_FILE: file_buttons(); break;
+ case SPACE_INFO: info_buttons(); break;
+ case SPACE_VIEW3D: view3d_buttons(); break;
+ case SPACE_IPO: ipo_buttons(); break;
+ case SPACE_BUTS: buts_buttons(); break;
+ case SPACE_SEQ: seq_buttons(); break;
+ case SPACE_IMAGE: image_buttons(); break;
+ case SPACE_IMASEL: imasel_buttons(); break;
+ case SPACE_OOPS: oops_buttons(); break;
+ case SPACE_TEXT: text_buttons(); break;
+ case SPACE_SOUND: sound_buttons(); break;
+ case SPACE_ACTION: action_buttons(); break;
+ case SPACE_NLA: nla_buttons(); break;
+ }
+
+ area->head_swap= WIN_BACK_OK;
+}
+void scrarea_do_headchange(ScrArea *area)
+{
+ float ofs= area->headbutofs;
+
+ if (area->headertype==HEADERDOWN) {
+ bwin_ortho2(area->headwin, 0.5+ofs, area->headrct.xmax-area->headrct.xmin-0.5+ofs, +0.6, area->headrct.ymax-area->headrct.ymin+0.6);
+ } else {
+ bwin_ortho2(area->headwin, -0.5+ofs, area->headrct.xmax-area->headrct.xmin-0.5+ofs, -0.5, area->headrct.ymax-area->headrct.ymin-0.5);
+ }
+}
+
+
+static void openheadwin(ScrArea *sa);
+static void closeheadwin(ScrArea *sa);
+
+static void scrarea_change_headertype(ScrArea *sa, int newtype)
+{
+ sa->headertype= newtype;
+
+ if (!newtype) {
+ if (sa->headwin) {
+ uiFreeBlocksWin(&sa->uiblocks, sa->headwin);
+ closeheadwin(sa);
+ }
+ } else {
+ if (!sa->headwin) {
+ openheadwin(sa);
+ }
+ }
+
+ testareas();
+ winqueue_break= 1;
+}
+
+static void headmenu(ScrArea *sa)
+{
+ short val= pupmenu("Header %t|Top%x2|Bottom %x1|No Header %x0");
+
+ if(val> -1) {
+ scrarea_change_headertype(sa, val);
+ }
+}
+
+static void addqueue_ext(short win, unsigned short event, short val, char ascii)
+{
+ if (win<4 || !areawinar[win]) {
+ printf("bad call to addqueue: %d (%d, %d)\n", win, event, val);
+ } else {
+ bwin_qadd(win, event, val, ascii);
+ }
+}
+
+void addqueue(short win, unsigned short event, short val)
+{
+ addqueue_ext(win, event, val, 0);
+}
+
+void scrarea_queue_winredraw(ScrArea *area)
+{
+ addqueue(area->win, REDRAW, 1);
+}
+void scrarea_queue_headredraw(ScrArea *area)
+{
+ if (area->headwin) addqueue(area->headwin, REDRAW, 1);
+}
+void scrarea_queue_redraw(ScrArea *area)
+{
+ scrarea_queue_winredraw(area);
+ scrarea_queue_headredraw(area);
+}
+
+static void scrollheader(ScrArea *area);
+static void scrarea_dispatch_header_events(ScrArea *sa)
+{
+ ScrArea *tempsa;
+ short do_redraw=0, do_change=0;
+
+ areawinset(sa->headwin);
+
+ while(bwin_qtest(sa->headwin)) {
+ char ascii;
+ short val;
+ unsigned short event= bwin_qread(sa->headwin, &val, &ascii);
+
+ if(val) {
+ if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
+
+ switch(event) {
+ case UI_BUT_EVENT:
+ do_headerbuttons(val);
+ break;
+
+ case LEFTMOUSE:
+ if (G.qual & LR_CTRLKEY) {
+ window_lower(mainwin);
+ } else {
+ window_raise(mainwin);
+ }
+ break;
+
+ case MIDDLEMOUSE:
+ scrollheader(sa);
+ break;
+ case RIGHTMOUSE:
+ headmenu(sa);
+ break;
+ case REDRAW:
+ do_redraw= 1;
+ break;
+ case CHANGED:
+ sa->head_swap= 0;
+ do_change= 1;
+ do_redraw= 1;
+ break;
+ default:
+ if (winqueue_break == 0) {
+ scrarea_do_winhandle(sa, event, val, ascii);
+ if (winqueue_break == 0) areawinset(sa->headwin);
+ }
+ }
+
+ if(winqueue_break) return;
+ }
+ }
+
+ /* test: bestaat window nog */
+ tempsa= areawinar[sa->headwin];
+ if(tempsa==0) return;
+
+ /* dit onderscheid loopt niet lekker... */
+ if(do_change) scrarea_do_headchange(sa);
+ if(do_redraw) scrarea_do_headdraw(sa);
+}
+
+static void scrarea_dispatch_events(ScrArea *sa)
+{
+ ScrArea *tempsa;
+ short do_redraw=0, do_change=0;
+
+ if(sa!=curarea || sa->win!=mywinget()) areawinset(sa->win);
+
+ while(bwin_qtest(sa->win)) {
+ char ascii;
+ short val;
+ unsigned short event= bwin_qread(sa->win, &val, &ascii);
+
+ if(event==REDRAW) {
+ do_redraw= 1;
+ }
+ else if(event==CHANGED) {
+ sa->win_swap= 0;
+ do_change= 1;
+ do_redraw= 1;
+ }
+ else {
+ scrarea_do_winhandle(sa, event, val, ascii);
+ }
+
+ if(winqueue_break) return;
+ }
+
+ /* test: bestaat window nog */
+ tempsa= areawinar[sa->win];
+ if(tempsa==0) return;
+
+ if (do_change || do_redraw) {
+ areawinset(sa->win);
+ if(do_change)
+ scrarea_do_winchange(curarea);
+ if(do_redraw)
+ scrarea_do_windraw(curarea);
+ }
+}
+
+/***/
+
+
+void markdirty_all()
+{
+ ScrArea *sa;
+
+ for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
+ scrarea_queue_winredraw(sa);
+ sa->win_swap &= ~WIN_FRONT_OK;
+
+ scrarea_queue_headredraw(sa);
+ sa->head_swap &= ~WIN_FRONT_OK;
+ }
+}
+
+int is_allowed_to_change_screen(bScreen *new)
+{
+ /* niet als curscreen is full
+ * niet als obedit && old->scene!=new->scene
+ */
+
+ if(new==0) return 0;
+ if(G.curscreen->full != SCREENNORMAL) return 0;
+ if(curarea->full) return 0;
+ if(G.obedit) {
+ if(G.curscreen->scene!=new->scene) return 0;
+ }
+ return 1;
+}
+
+void splash(void *data, int datasize, char *string)
+{
+ ImBuf *bbuf;
+ int oldwin;
+ short val;
+
+ bbuf= IMB_ibImageFromMemory((int *)data, datasize, IB_rect);
+
+ if (bbuf) {
+
+ oldwin = mywinget();
+ mywinset(G.curscreen->mainwin);
+
+ if (string) {
+ int x, y, maxy;
+ unsigned int *rect;
+
+ rect = bbuf->rect;
+ maxy = MIN2(bbuf->y, 18);
+
+ for (y = 0; y < maxy; y++) {
+ for (x = 0; x < bbuf->x; x++) {
+ *rect = 0xffffffff;
+ rect++;
+ }
+ }
+ }
+ glDrawBuffer(GL_FRONT);
+
+ /*
+ // this dims the whole screen a bit. I didn't like it afterall
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glColor4f(0.0,0.0,0.0,0.3);
+ glRecti(0, 0, G.curscreen->sizex, G.curscreen->sizey);
+ glDisable(GL_BLEND);
+ */
+
+ glRasterPos2i((prefsizx-bbuf->x)/2, (prefsizy-bbuf->y)/2);
+ glDrawPixels(bbuf->x, bbuf->y, GL_RGBA, GL_UNSIGNED_BYTE, bbuf->rect);
+
+ if (string) {
+ void *font;
+ int width;
+
+ if (BMF_GetStringWidth(font= G.font, string) > bbuf->x)
+ if (BMF_GetStringWidth(font= G.fonts, string) > bbuf->x)
+ font= G.fontss;
+
+ width= BMF_GetStringWidth(font, string);
+
+ glColor3ub(0, 0, 0);
+ glRasterPos2i((prefsizx-width)/2, (prefsizy-bbuf->y)/2 + 6);
+ BMF_DrawString(font, string);
+ }
+
+ glFinish();
+ glDrawBuffer(GL_BACK);
+
+ IMB_freeImBuf(bbuf);
+
+ // flush input buffers ....
+ // this might break some things
+
+ while (get_mbut()) {
+ BIF_wait_for_statechange();
+ }
+ while(qtest()) {
+ extern_qread(&val);
+ }
+
+ wait_for_event();
+
+ mywinset(oldwin);
+ markdirty_all();
+ mainqenter(DRAWEDGES, 1);
+ }
+}
+
+static void moveareas(ScrEdge *edge);
+static void joinarea(ScrArea *sa, ScrEdge *onedge);
+static void splitarea_interactive(ScrArea *area, ScrEdge *onedge);
+
+static void screen_edge_edit_event(ScrArea *actarea, ScrEdge *actedge, short evt, short val) {
+ if (val) {
+ // don't allow users to edit full screens
+ if (actarea && actarea->full) {
+ return;
+ }
+
+ if (evt==LEFTMOUSE) {
+ moveareas(actedge);
+ } else if (evt==MIDDLEMOUSE || evt==RIGHTMOUSE) {
+ int edgeop;
+
+ if (!actarea->headertype) {
+ edgeop= pupmenu("Split Area|Join Areas|Add header");
+ } else {
+ edgeop= pupmenu("Split Area|Join Areas|No header");
+ }
+
+ if (edgeop==1) {
+ splitarea_interactive(actarea, actedge);
+ } else if (edgeop==2) {
+ joinarea(actarea, actedge);
+ } else if (edgeop==3) {
+ scrarea_change_headertype(actarea, actarea->headertype?0:HEADERDOWN);
+ }
+ }
+ }
+}
+
+/***/
+
+void mywindow_init_mainwin(Window *win, int orx, int ory, int sizex, int sizey);
+void test_scale_screen(bScreen *);
+
+static void resize_screens(int x, int y, int w, int h) {
+ prefstax= x;
+ prefstay= y;
+ prefsizx= w;
+ prefsizy= h;
+
+ test_scale_screen(G.curscreen);
+ testareas();
+}
+
+static void init_mainwin(void)
+{
+ int orx, ory, sizex, sizey;
+
+ glEnable(GL_SCISSOR_TEST);
+
+ window_get_position(mainwin, &orx, &ory);
+ window_get_size(mainwin, &sizex, &sizey);
+
+ /* XXX, temporary stupid fix for minimize at windows */
+ if (!sizex && !sizey) {
+ return;
+ }
+
+ mywindow_init_mainwin(mainwin, orx, ory, sizex, sizey);
+ resize_screens(orx, ory, sizex, sizey);
+}
+
+/***/
+
+static short afterqueue[MAXQUEUE][3];
+static int nafterqitems= 0;
+
+void addafterqueue(short win, unsigned short evt, short val)
+{
+ if (nafterqitems<MAXQUEUE) {
+ afterqueue[nafterqitems][0]= win;
+ afterqueue[nafterqitems][1]= evt;
+ afterqueue[nafterqitems][2]= val;
+ nafterqitems++;
+ }
+}
+
+static void append_afterqueue(void)
+{
+ while (nafterqitems) {
+ short win= afterqueue[nafterqitems-1][0];
+ unsigned short evt= afterqueue[nafterqitems-1][1];
+ short val= afterqueue[nafterqitems-1][2];
+
+ addqueue(win, evt, val);
+
+ nafterqitems--;
+ }
+}
+
+static char ext_load_str[256]= {0, 0};
+void add_readfile_event(char *filename)
+{
+ mainqenter(LOAD_FILE, 1);
+ strcpy(ext_load_str, filename);
+ BLI_convertstringcode(ext_load_str, G.sce, G.scene->r.cfra);
+}
+
+static short ext_reshape= 0, ext_redraw=0, ext_inputchange=0, ext_mousemove=0;
+
+static void flush_extqd_events(void) {
+ if (ext_inputchange) {
+ mainqenter(INPUTCHANGE, ext_inputchange);
+ } else if (ext_reshape) {
+ mainqenter(RESHAPE, ext_redraw);
+ } else if (ext_redraw) {
+ mainqenter(REDRAW, ext_redraw);
+ } else if (ext_mousemove) {
+ short mouse[2];
+
+ getmouseco_sc(mouse);
+
+ mainqenter(MOUSEX, mouse[0]);
+ mainqenter(MOUSEY, mouse[1]);
+ }
+
+ ext_inputchange= ext_reshape= ext_redraw= ext_mousemove= 0;
+}
+
+unsigned short qtest(void)
+{
+ if (!mainqtest()) {
+ winlay_process_events(0);
+ }
+
+ return mainqtest();
+}
+
+ /* return true if events are waiting anywhere */
+int anyqtest(void)
+{
+ ScrArea *sa;
+
+ if (nafterqitems || qtest()) return 1;
+
+ for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
+ if (bwin_qtest(sa->win)) return 1;
+ if (sa->headwin && bwin_qtest(sa->headwin)) return 1;
+ }
+
+ return 0;
+}
+
+static void wait_for_event(void)
+{
+ while (!mainqtest()) {
+ winlay_process_events(1);
+ }
+}
+
+unsigned short screen_qread(short *val, char *ascii)
+{
+ unsigned short event;
+
+ wait_for_event();
+
+ event= mainqread(val, ascii);
+
+ if(event==RIGHTSHIFTKEY || event==LEFTSHIFTKEY) {
+ if(*val) G.qual |= LR_SHIFTKEY;
+ else G.qual &= ~LR_SHIFTKEY;
+ }
+ else if(event==RIGHTALTKEY || event==LEFTALTKEY) {
+ if(*val) G.qual |= LR_ALTKEY;
+ else G.qual &= ~LR_ALTKEY;
+ }
+ else if(event==RIGHTCTRLKEY || event==LEFTCTRLKEY) {
+ if(*val) G.qual |= LR_CTRLKEY;
+ else G.qual &= ~LR_CTRLKEY;
+ }
+
+ return event;
+}
+
+unsigned short extern_qread_ext(short *val, char *ascii)
+{
+ /* bewaart de laatste INPUTCHANGE en de laatste REDRAW */
+ unsigned short event;
+
+ event= screen_qread(val, ascii);
+ if(event==RESHAPE) ext_reshape= *val;
+ else if(event==REDRAW) ext_redraw= *val;
+ else if(event==INPUTCHANGE) ext_inputchange= *val;
+ else if(event==MOUSEY || event==MOUSEX) ext_mousemove= 1;
+ else if((G.qual & LR_CTRLKEY) && event==F3KEY) {
+ BIF_screendump();
+ }
+
+ return event;
+}
+unsigned short extern_qread(short *val)
+{
+ char ascii;
+ return extern_qread_ext(val, &ascii);
+}
+
+void reset_autosave(void) {
+ window_set_timer(mainwin, U.savetime*60*1000, AUTOSAVE_FILE);
+}
+
+static void screen_dispatch_events(void) {
+ int events_remaining= 1;
+ ScrArea *sa;
+
+ while (events_remaining) {
+ events_remaining= 0;
+
+ winqueue_break= 0;
+ for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
+ /* bewust eerst header afhandelen, dan rest. Header is soms init */
+ if (sa->headwin && bwin_qtest(sa->headwin)) {
+ scrarea_dispatch_header_events(sa);
+ events_remaining= 1;
+ }
+ if (winqueue_break) break;
+
+ if (bwin_qtest(sa->win)) {
+ scrarea_dispatch_events(sa);
+ events_remaining= 1;
+ }
+ if (winqueue_break) break;
+ }
+
+ if (winqueue_break) break;
+ }
+
+ if (dodrawscreen) {
+ drawscreen();
+ dodrawscreen= 0;
+ }
+
+ screen_swapbuffers();
+}
+
+static ScrArea *screen_find_area_for_pt(bScreen *sc, short *mval)
+{
+ ScrArea *sa;
+
+ for (sa= sc->areabase.first; sa; sa= sa->next)
+ if (BLI_in_rcti(&sa->totrct, mval[0], mval[1]))
+ return sa;
+
+ return NULL;
+}
+
+void screenmain(void)
+{
+ int has_input= 1;
+ int firsttime = 1;
+ while (1) {
+ unsigned short event;
+ short val, towin;
+ char ascii;
+
+ flush_extqd_events();
+ if (nafterqitems && !qtest()) {
+ append_afterqueue();
+ event= 0;
+ } else {
+ event= screen_qread(&val, &ascii);
+ }
+
+ window_make_active(mainwin);
+
+ if (event==INPUTCHANGE) {
+ has_input= val;
+ }
+
+ if (has_input) {
+ ScrArea *newactarea;
+ int newactwin;
+ short mval[2];
+
+ getmouseco_sc(mval);
+ newactarea= screen_find_area_for_pt(G.curscreen, mval);
+
+ if (newactarea) {
+ if (BLI_in_rcti(&newactarea->headrct, mval[0], mval[1])) {
+ newactwin= newactarea->headwin;
+ } else {
+ newactwin= newactarea->win;
+ }
+ } else {
+ newactwin= 0;
+ }
+
+ if (newactarea && (newactarea != g_activearea)) {
+ if (g_activearea) scrarea_queue_headredraw(g_activearea);
+ scrarea_queue_headredraw(newactarea);
+ set_cursor(newactarea->cursor);
+ g_activearea= newactarea;
+ }
+
+ G.curscreen->winakt= newactwin;
+ if (G.curscreen->winakt) {
+ areawinset(G.curscreen->winakt);
+ set_cursor(choose_cursor(g_activearea));
+ }
+ } else {
+ if (g_activearea) {
+ scrarea_queue_headredraw(g_activearea);
+ }
+ g_activearea= NULL;
+ G.curscreen->winakt= 0;
+ }
+
+ towin= 0;
+ if (event==WINCLOSE) {
+ exit_usiblender();
+ }
+ else if (event==DRAWEDGES) {
+ dodrawscreen= 1;
+ }
+ else if (event==RESHAPE) {
+ init_mainwin();
+ markdirty_all();
+ dodrawscreen= 1;
+ }
+ else if (event==REDRAW) {
+ markdirty_all();
+ dodrawscreen= 1;
+ }
+ else if (event==AUTOSAVE_FILE) {
+ BIF_write_autosave();
+ }
+ else if (event==LOAD_FILE) {
+ BIF_read_file(ext_load_str);
+ sound_initialize_sounds();
+ }
+ else {
+ towin= 1;
+ }
+
+ if (!g_activearea) {
+ towin= 0;
+ }
+ else if (!G.curscreen->winakt) {
+ ScrEdge *actedge;
+ short mval[2];
+
+ getmouseco_sc(mval);
+ actedge= screen_find_active_scredge(G.curscreen, mval);
+
+ if (actedge) {
+ if (scredge_is_horizontal(actedge)) {
+ set_cursor(CURSOR_Y_MOVE);
+ } else {
+ set_cursor(CURSOR_X_MOVE);
+ }
+
+ screen_edge_edit_event(g_activearea, actedge, event, val);
+ } else {
+ set_cursor(CURSOR_STD);
+ }
+
+ towin= 0;
+ }
+ else if (event==QKEY) {
+ if((G.obedit && G.obedit->type==OB_FONT && g_activearea->spacetype==SPACE_VIEW3D)||g_activearea->spacetype==SPACE_TEXT);
+ else {
+ if(val && okee("QUIT BLENDER")) exit_usiblender();
+ towin= 0;
+ }
+ }
+ else if (event==ZKEY) {
+ if(val && G.qual==(LR_ALTKEY|LR_SHIFTKEY|LR_CTRLKEY)) {
+ extern void set_debug_swapbuffers_ovveride(bScreen *sc, int mode);
+
+ int which= pupmenu("Swapbuffers%t|Simple|Debug|DebugSwap|Redraw|Default|KillSwap");
+
+ switch (which) {
+ case 1: set_debug_swapbuffers_ovveride(G.curscreen, 's'); break;
+ case 2: set_debug_swapbuffers_ovveride(G.curscreen, 'd'); break;
+ case 3: set_debug_swapbuffers_ovveride(G.curscreen, 'f'); break;
+ case 4: set_debug_swapbuffers_ovveride(G.curscreen, 'r'); break;
+ case 5: set_debug_swapbuffers_ovveride(G.curscreen, 0); break;
+ case 6:
+ if (g_activearea) {
+ g_activearea->head_swap= 0;
+ g_activearea->win_swap= 0;
+ }
+ break;
+ }
+ towin= 0;
+ }
+ }
+ else if (event==SPACEKEY) {
+ if((G.obedit && G.obedit->type==OB_FONT && g_activearea->spacetype==SPACE_VIEW3D)||g_activearea->spacetype==SPACE_TEXT);
+ else {
+ if(val) toolbox();
+ towin= 0;
+ }
+ }
+ else if(ELEM(event, LEFTARROWKEY, RIGHTARROWKEY)) {
+ if(val && (G.qual & LR_CTRLKEY)) {
+ bScreen *sc= (event==LEFTARROWKEY)?G.curscreen->id.prev:G.curscreen->id.next;
+ if(is_allowed_to_change_screen(sc)) setscreen(sc);
+ g_activearea= NULL;
+ towin= 0;
+ }
+ }
+ else if(ELEM(event, UPARROWKEY, DOWNARROWKEY)) {
+ if(val && (G.qual & LR_CTRLKEY)) {
+ area_fullscreen();
+ g_activearea= NULL;
+ towin= 0;
+ }
+ }
+
+ if (towin) {
+ if (blenderqread(event, val))
+ addqueue_ext(G.curscreen->winakt, event, val, ascii);
+ }
+
+ /* only process subwindow queue's once the
+ * main queue has been emptyied.
+ */
+ event= qtest();
+ if (event==0 || event==EXECUTE) {
+ screen_dispatch_events();
+ }
+
+ /* Bizar hack. The event queue has mutated... */
+ if ( (firsttime) && (event == 0) ) {
+ if (G.fileflags & G_FILE_AUTOPLAY) {
+ // SET AUTOPLAY in G.flags for
+ // other fileloads
+
+ G.flags |= G_FLAGS_AUTOPLAY;
+ area_autoplayscreen();
+
+ // Let The Games Begin
+ // fake a 'p' keypress
+
+ mainqenter(PKEY, 1);
+ } else {
+ extern char datatoc_splash_jpg[];
+ extern int datatoc_splash_jpg_size;
+ extern char datatoc_ton[];
+ extern int datatoc_tonize;
+
+ if (! ((G.main->versionfile >= G.version)
+ || G.save_over)) {
+ if (LICENSE_KEY_VALID) {
+ splash((void *)datatoc_ton,
+ datatoc_tonize,
+ NULL);
+ } else {
+ splash((void *)datatoc_splash_jpg,
+ datatoc_splash_jpg_size,
+ NULL);
+ }
+ }
+ }
+ firsttime = 0;
+ }
+ }
+}
+
+void mainwindow_raise(void) {
+ window_raise(mainwin);
+}
+void mainwindow_make_active(void) {
+ window_make_active(mainwin);
+}
+void mainwindow_close(void) {
+ window_destroy(mainwin);
+ mainwin= NULL;
+}
+
+/* ********* AREAS ************* */
+
+void setprefsize(int stax, int stay, int sizx, int sizy)
+{
+ int scrwidth, scrheight;
+
+ winlay_get_screensize(&scrwidth, &scrheight);
+
+ if(stax<0) stax= 0;
+ if(stay<0) stay= 0;
+ if(sizx<320) sizx= 320;
+ if(sizy<256) sizy= 256;
+
+ if(stax+sizx>scrwidth) sizx= scrwidth-stax;
+ if(stay+sizy>scrheight) sizy= scrheight-stay;
+ if(sizx<320 || sizy<256) {
+ printf("ERROR: illegal prefsize\n");
+ return;
+ }
+
+ prefstax= stax;
+ prefstay= stay;
+ prefsizx= sizx;
+ prefsizy= sizy;
+
+ start_maximized= 0;
+}
+
+
+static ScrVert *screen_addvert(bScreen *sc, short x, short y)
+{
+ ScrVert *sv= MEM_callocN(sizeof(ScrVert), "addscrvert");
+ sv->vec.x= x;
+ sv->vec.y= y;
+
+ BLI_addtail(&sc->vertbase, sv);
+ return sv;
+}
+
+static void sortscrvert(ScrVert **v1, ScrVert **v2)
+{
+ ScrVert *tmp;
+
+ if ((long)*v1 > (long)*v2) {
+ tmp= *v1;
+ *v1= *v2;
+ *v2= tmp;
+ }
+}
+
+static ScrEdge *screen_addedge(bScreen *sc, ScrVert *v1, ScrVert *v2)
+{
+ ScrEdge *se= MEM_callocN(sizeof(ScrEdge), "addscredge");
+
+ sortscrvert(&v1, &v2);
+ se->v1= v1;
+ se->v2= v2;
+
+ BLI_addtail(&sc->edgebase, se);
+ return se;
+}
+
+static ScrEdge *screen_findedge(bScreen *sc, ScrVert *v1, ScrVert *v2)
+{
+ ScrEdge *se;
+
+ sortscrvert(&v1, &v2);
+ for (se= sc->edgebase.first; se; se= se->next)
+ if(se->v1==v1 && se->v2==v2)
+ return se;
+
+ return NULL;
+}
+
+static void removedouble_scrverts(void)
+{
+ ScrVert *v1, *verg;
+ ScrEdge *se;
+ ScrArea *sa;
+
+ verg= G.curscreen->vertbase.first;
+ while(verg) {
+ if(verg->newv==0) { /* !!! */
+ v1= verg->next;
+ while(v1) {
+ if(v1->newv==0) { /* !?! */
+ if(v1->vec.x==verg->vec.x && v1->vec.y==verg->vec.y) {
+ /* printf("doublevert\n"); */
+ v1->newv= verg;
+ }
+ }
+ v1= v1->next;
+ }
+ }
+ verg= verg->next;
+ }
+
+ /* vervang pointers in edges en vlakken */
+ se= G.curscreen->edgebase.first;
+ while(se) {
+ if(se->v1->newv) se->v1= se->v1->newv;
+ if(se->v2->newv) se->v2= se->v2->newv;
+ /* edges zijn veranderd: dus.... */
+ sortscrvert(&(se->v1), &(se->v2));
+ se= se->next;
+ }
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa->v1->newv) sa->v1= sa->v1->newv;
+ if(sa->v2->newv) sa->v2= sa->v2->newv;
+ if(sa->v3->newv) sa->v3= sa->v3->newv;
+ if(sa->v4->newv) sa->v4= sa->v4->newv;
+ sa= sa->next;
+ }
+
+ /* verwijderen */
+ verg= G.curscreen->vertbase.first;
+ while(verg) {
+ v1= verg->next;
+ if(verg->newv) {
+ BLI_remlink(&G.curscreen->vertbase, verg);
+ MEM_freeN(verg);
+ }
+ verg= v1;
+ }
+
+}
+
+static void removenotused_scrverts(void)
+{
+ ScrVert *sv, *svn;
+ ScrEdge *se;
+
+ /* ga ervan uit dat de edges goed zijn */
+
+ se= G.curscreen->edgebase.first;
+ while(se) {
+ se->v1->flag= 1;
+ se->v2->flag= 1;
+ se= se->next;
+ }
+
+ sv= G.curscreen->vertbase.first;
+ while(sv) {
+ svn= sv->next;
+ if(sv->flag==0) {
+ BLI_remlink(&G.curscreen->vertbase, sv);
+ MEM_freeN(sv);
+ }
+ else sv->flag= 0;
+ sv= svn;
+ }
+}
+
+static void removedouble_scredges(void)
+{
+ ScrEdge *verg, *se, *sn;
+
+ /* vergelijken */
+ verg= G.curscreen->edgebase.first;
+ while(verg) {
+ se= verg->next;
+ while(se) {
+ sn= se->next;
+ if(verg->v1==se->v1 && verg->v2==se->v2) {
+ BLI_remlink(&G.curscreen->edgebase, se);
+ MEM_freeN(se);
+ }
+ se= sn;
+ }
+ verg= verg->next;
+ }
+}
+
+static void removenotused_scredges(void)
+{
+ ScrEdge *se, *sen;
+ ScrArea *sa;
+ int a=0;
+
+ /* zet flag als edge gebruikt wordt in area */
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ se= screen_findedge(G.curscreen, sa->v1, sa->v2);
+ if(se==0) printf("error: area %d edge 1 bestaat niet\n", a);
+ else se->flag= 1;
+ se= screen_findedge(G.curscreen, sa->v2, sa->v3);
+ if(se==0) printf("error: area %d edge 2 bestaat niet\n", a);
+ else se->flag= 1;
+ se= screen_findedge(G.curscreen, sa->v3, sa->v4);
+ if(se==0) printf("error: area %d edge 3 bestaat niet\n", a);
+ else se->flag= 1;
+ se= screen_findedge(G.curscreen, sa->v4, sa->v1);
+ if(se==0) printf("error: area %d edge 4 bestaat niet\n", a);
+ else se->flag= 1;
+ sa= sa->next;
+ a++;
+ }
+ se= G.curscreen->edgebase.first;
+ while(se) {
+ sen= se->next;
+ if(se->flag==0) {
+ BLI_remlink(&G.curscreen->edgebase, se);
+ MEM_freeN(se);
+ }
+ else se->flag= 0;
+ se= sen;
+ }
+}
+
+void calc_arearcts(ScrArea *sa)
+{
+
+ if(sa->v1->vec.x>0) sa->totrct.xmin= sa->v1->vec.x+EDGEWIDTH2+1;
+ else sa->totrct.xmin= sa->v1->vec.x;
+ if(sa->v4->vec.x<G.curscreen->sizex-1) sa->totrct.xmax= sa->v4->vec.x-EDGEWIDTH2-1;
+ else sa->totrct.xmax= sa->v4->vec.x;
+
+ if(sa->v1->vec.y>0) sa->totrct.ymin= sa->v1->vec.y+EDGEWIDTH2+1;
+ else sa->totrct.ymin= sa->v1->vec.y;
+ if(sa->v2->vec.y<G.curscreen->sizey-1) sa->totrct.ymax= sa->v2->vec.y-EDGEWIDTH2-1;
+ else sa->totrct.ymax= sa->v2->vec.y;
+
+ sa->winrct= sa->totrct;
+ if(sa->headertype) {
+ sa->headrct= sa->totrct;
+ if(sa->headertype==HEADERDOWN) {
+ sa->headrct.ymax= sa->headrct.ymin+HEADERY-1;
+ sa->winrct.ymin= sa->headrct.ymax+1;
+ }
+ else if(sa->headertype==HEADERTOP) {
+ sa->headrct.ymin= sa->headrct.ymax-HEADERY+1;
+ sa->winrct.ymax= sa->headrct.ymin-1;
+ }
+ }
+ if(sa->winrct.ymin>sa->winrct.ymax) sa->winrct.ymin= sa->winrct.ymax;
+
+ /* als speedup voor berekeningen */
+ sa->winx= sa->winrct.xmax-sa->winrct.xmin+1;
+ sa->winy= sa->winrct.ymax-sa->winrct.ymin+1;
+}
+
+static void openheadwin(ScrArea *sa)
+{
+ sa->headwin= myswinopen(G.curscreen->mainwin,
+ sa->headrct.xmin, sa->headrct.xmax, sa->headrct.ymin, sa->headrct.ymax);
+
+ glMatrixMode(GL_MODELVIEW);
+
+ areawinar[sa->headwin]= sa; /* anders doet addqueue het niet */
+ addqueue(sa->headwin, CHANGED, 1);
+}
+
+static void openareawin(ScrArea *sa)
+{
+ sa->win= myswinopen(G.curscreen->mainwin,
+ sa->winrct.xmin, sa->winrct.xmax, sa->winrct.ymin, sa->winrct.ymax);
+
+ areawinar[sa->win]= sa; /* anders doet addqueue het niet */
+ addqueue(sa->win, CHANGED, 1);
+}
+
+static void closeheadwin(ScrArea *sa)
+{
+ if(sa->headwin) mywinclose(sa->headwin);
+ sa->headwin= 0;
+}
+
+static void closeareawin(ScrArea *sa)
+{
+ uiFreeBlocksWin(&sa->uiblocks, sa->win);
+
+ if(sa->win) mywinclose(sa->win);
+ sa->win= 0;
+}
+
+static void del_area(ScrArea *sa)
+{
+ closeareawin(sa);
+ closeheadwin(sa);
+
+ freespacelist(&sa->spacedata);
+
+ uiFreeBlocks(&sa->uiblocks);
+
+ if(sa==curarea) curarea= 0;
+ if(sa==g_activearea) g_activearea= 0;
+}
+
+static void copy_areadata(ScrArea *sa1, ScrArea *sa2)
+{
+ sa1->headertype= sa2->headertype;
+ sa1->spacetype= sa2->spacetype;
+ Mat4CpyMat4(sa1->winmat, sa2->winmat);
+
+ freespacelist(&sa1->spacedata);
+
+ duplicatespacelist(sa1, &sa1->spacedata, &sa2->spacedata);
+}
+
+static ScrArea *screen_addarea(bScreen *sc, ScrVert *v1, ScrVert *v2, ScrVert *v3, ScrVert *v4, short headertype, short spacetype)
+{
+ ScrArea *sa= MEM_callocN(sizeof(ScrArea), "addscrarea");
+ sa->cursor= CURSOR_STD;
+ sa->v1= v1;
+ sa->v2= v2;
+ sa->v3= v3;
+ sa->v4= v4;
+ sa->headertype= headertype;
+ sa->spacetype= spacetype;
+
+ calc_arearcts(sa);
+
+ if (sa->headertype) openheadwin(sa);
+ openareawin(sa);
+
+ BLI_addtail(&sc->areabase, sa);
+ return sa;
+}
+
+static int rcti_eq(rcti *a, rcti *b) {
+ return ((a->xmin==b->xmin && a->xmax==b->xmax) &&
+ (a->ymin==b->ymin && a->ymax==b->ymax));
+}
+
+static void testareas(void)
+{
+ ScrArea *sa;
+
+ /* testen of header er moet zijn, of weg moet, of verplaatst */
+ /* testen of window er moet zijn, of weg moet, of verplaatst */
+
+ for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
+ rcti oldhr= sa->headrct;
+ rcti oldwr= sa->winrct;
+
+ calc_arearcts(sa);
+
+ /* test header */
+ if (sa->headwin) {
+ if (!rcti_eq(&oldhr, &sa->headrct)) {
+ mywinposition(sa->headwin, sa->headrct.xmin, sa->headrct.xmax, sa->headrct.ymin, sa->headrct.ymax);
+ addqueue(sa->headwin, CHANGED, 1);
+ }
+
+ if(sa->headbutlen<sa->winx) {
+ sa->headbutofs= 0;
+ addqueue(sa->headwin, CHANGED, 1);
+ }
+ else if(sa->headbutofs+sa->winx > sa->headbutlen) {
+ sa->headbutofs= sa->headbutlen-sa->winx;
+ addqueue(sa->headwin, CHANGED, 1);
+ }
+ }
+
+ if (!rcti_eq(&oldwr, &sa->winrct)) {
+ mywinposition(sa->win, sa->winrct.xmin, sa->winrct.xmax, sa->winrct.ymin, sa->winrct.ymax);
+ addqueue(sa->win, CHANGED, 1);
+ }
+ }
+
+ /* remake global windowarray */
+ memset(areawinar, 0, sizeof(void *)*MAXWIN);
+ for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
+ areawinar[sa->headwin]= sa;
+ areawinar[sa->win]= sa;
+ }
+
+ /* test of winakt in orde is */
+ if( areawinar[G.curscreen->winakt]==0) G.curscreen->winakt= 0;
+}
+
+static ScrArea *test_edge_area(ScrArea *sa, ScrEdge *se)
+{
+ /* test of edge in area ligt, zo niet,
+ vind een area die 'm wel heeft */
+
+ ScrEdge *se1=0, *se2=0, *se3=0, *se4=0;
+
+ if(sa) {
+ se1= screen_findedge(G.curscreen, sa->v1, sa->v2);
+ se2= screen_findedge(G.curscreen, sa->v2, sa->v3);
+ se3= screen_findedge(G.curscreen, sa->v3, sa->v4);
+ se4= screen_findedge(G.curscreen, sa->v4, sa->v1);
+ }
+ if(se1!=se && se2!=se && se3!=se && se4!=se) {
+
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ /* een beetje optimaliseren? */
+ if(se->v1==sa->v1 || se->v1==sa->v2 || se->v1==sa->v3 || se->v1==sa->v4) {
+ se1= screen_findedge(G.curscreen, sa->v1, sa->v2);
+ se2= screen_findedge(G.curscreen, sa->v2, sa->v3);
+ se3= screen_findedge(G.curscreen, sa->v3, sa->v4);
+ se4= screen_findedge(G.curscreen, sa->v4, sa->v1);
+ if(se1==se || se2==se || se3==se || se4==se) return sa;
+ }
+ sa= sa->next;
+ }
+ }
+
+ return sa; /* is keurig 0 als niet gevonden */
+}
+
+ScrArea *closest_bigger_area(void)
+{
+ ScrArea *sa, *big=0;
+ float cent[3], vec[3],len, len1, len2, len3, dist=1000;
+ short mval[2];
+
+ getmouseco_sc(mval);
+
+ cent[0]= mval[0];
+ cent[1]= mval[1];
+ cent[2]= vec[2]= 0;
+
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa!=curarea) {
+ if(sa->winy>=curarea->winy) {
+
+ /* mimimum van vier hoekpunten */
+ vec[0]= sa->v1->vec.x; vec[1]= sa->v1->vec.y;
+ len= VecLenf(vec, cent);
+ vec[0]= sa->v2->vec.x; vec[1]= sa->v2->vec.y;
+ len1= VecLenf(vec, cent);
+ vec[0]= sa->v3->vec.x; vec[1]= sa->v3->vec.y;
+ len2= VecLenf(vec, cent);
+ vec[0]= sa->v4->vec.x; vec[1]= sa->v4->vec.y;
+ len3= VecLenf(vec, cent);
+
+ len= MIN4(len, len1, len2, len3);
+
+ /* plus centrum */
+ vec[0]= (sa->v2->vec.x+sa->v3->vec.x)/2;
+ vec[1]= (sa->v1->vec.y+sa->v2->vec.y)/2;
+
+ len+= 0.5*VecLenf(vec, cent);
+
+ /* min afmeting */
+ len-= sa->winy+sa->winx;
+
+ if(len<dist) {
+ dist= len;
+ big= sa;
+ }
+ }
+ }
+ sa= sa->next;
+ }
+
+ if(big) return big;
+ else return curarea;
+}
+
+/* ************ SCREENBEHEER ************** */
+
+static int statechanged= 0;
+void BIF_wait_for_statechange(void)
+{
+ if (!statechanged) {
+ /* Safety, don't wait more than 0.1 seconds */
+ double stime= PIL_check_seconds_timer();
+ while (!statechanged) {
+ winlay_process_events(1);
+ if ((PIL_check_seconds_timer()-stime)>0.1) break;
+ }
+ statechanged= 0;
+ }
+}
+void getmouse(short *mval)
+{
+ winlay_process_events(0);
+ window_get_mouse(mainwin, mval);
+}
+short get_qual(void)
+{
+ winlay_process_events(0);
+ return window_get_qual(mainwin);
+}
+short get_mbut(void)
+{
+ winlay_process_events(0);
+ return window_get_mbut(mainwin);
+}
+
+static unsigned short convert_for_nonumpad(unsigned short event)
+{
+ if (event>=ZEROKEY && event<=NINEKEY) {
+ return event - ZEROKEY + PAD0;
+ } else if (event==MINUSKEY) {
+ return PADMINUS;
+ } else if (event==EQUALKEY) {
+ return PADPLUSKEY;
+ } else if (event==BACKSLASHKEY) {
+ return PADSLASHKEY;
+ } else {
+ return event;
+ }
+}
+
+void add_to_mainqueue(Window *win, void *user_data, short evt, short val, char ascii)
+{
+ short qual= window_get_qual(win);
+
+ statechanged= 1;
+
+ if (U.flag&NONUMPAD) {
+ evt= convert_for_nonumpad(evt);
+ }
+
+ /* enforce some guarentees about ascii values... these should
+ * be enforced in ghost probably - zr
+ */
+
+ if (!val || !isprint(ascii) || (qual&~LR_SHIFTKEY)) {
+ ascii= '\0';
+ }
+
+ mainqenter_ext(evt, val, ascii);
+}
+
+static bScreen *addscreen(char *name) /* gebruik de setprefsize() als je anders dan fullscreen wilt */
+{
+ /* deze functie zet de variabele G.curscreen
+ * omdat alle hulpfuncties moeten weten welk screen
+ */
+ bScreen *sc;
+ ScrVert *sv1, *sv2, *sv3, *sv4;
+ short startx, starty, endx, endy;
+
+ sc= G.curscreen= alloc_libblock(&G.main->screen, ID_SCR, name);
+
+ if (!prefsizx) {
+ prefstax= 0;
+ prefstay= 0;
+
+ winlay_get_screensize(&prefsizx, &prefsizy);
+ }
+
+ startx= prefstax;
+ starty= prefstay;
+ endx= prefstax+prefsizx-1;
+ endy= prefstay+prefsizy-1;
+
+ sc->startx= startx; sc->starty= starty;
+ sc->endx= endx; sc->endy= endy;
+ sc->sizex= sc->endx-sc->startx+1;
+ sc->sizey= sc->endy-sc->starty+1;
+
+ sc->scene= G.scene;
+
+ if (!mainwin) {
+ mainwin= window_open("Blender", sc->startx, sc->starty, sc->sizex, sc->sizey, start_maximized);
+ if (!mainwin) {
+ printf("ERROR: Unable to open Blender window\n");
+ exit(1);
+ }
+
+ window_set_handler(mainwin, add_to_mainqueue, NULL);
+ init_mainwin();
+ mywinset(1);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ myortho2(-0.5, sc->sizex-0.5, -0.5, sc->sizey-0.5);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glDrawBuffer(GL_FRONT);
+ glClearColor(.45, .45, .45, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glDrawBuffer(GL_BACK);
+
+ warp_pointer(sc->sizex/2, sc->sizey/2);
+
+ mainqenter(REDRAW, 1);
+ }
+
+ sc->mainwin= 1;
+
+ sv1= screen_addvert(sc, 0, 0);
+ sv2= screen_addvert(sc, 0, sc->endy-sc->starty);
+ sv3= screen_addvert(sc, sc->sizex-1, sc->sizey-1);
+ sv4= screen_addvert(sc, sc->sizex-1, 0);
+
+ screen_addedge(sc, sv1, sv2);
+ screen_addedge(sc, sv2, sv3);
+ screen_addedge(sc, sv3, sv4);
+ screen_addedge(sc, sv4, sv1);
+
+ screen_addarea(sc, sv1, sv2, sv3, sv4, HEADERDOWN, SPACE_INFO);
+
+ G.curscreen= sc;
+
+ return sc;
+}
+
+void setscreen(bScreen *sc)
+{
+ bScreen *sc1;
+ ScrArea *sa;
+ short mval[2];
+
+ if(sc->full) { /* vind de bijhorende full */
+ sc1= G.main->screen.first;
+ while(sc1) {
+ sa= sc1->areabase.first;
+ if(sa->full==sc) {
+ sc= sc1;
+ break;
+ }
+ sc1= sc1->id.next;
+ }
+ if(sc1==0) printf("setscreen error\n");
+ }
+
+ /* G.curscreen de-activeren */
+ if (G.curscreen && G.curscreen != sc) {
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa->win) mywinclose(sa->win);
+ sa->win= 0;
+ if(sa->headwin) mywinclose(sa->headwin);
+ sa->headwin= 0;
+
+ uiFreeBlocks(&sa->uiblocks);
+
+ sa= sa->next;
+ }
+ }
+
+ if (G.curscreen != sc) {
+ mywinset(sc->mainwin);
+ }
+
+ G.curscreen= sc;
+
+ for (sa= sc->areabase.first; sa; sa= sa->next) {
+ /* XXX, fixme zr */
+/* if (sa->win || sa->headwin) */
+/* printf("error in setscreen (win): %d, %d\n", sa->win, sa->headwin); */
+ if (!sa->win)
+ openareawin(sa);
+ if (!sa->headwin && sa->headertype)
+ openheadwin(sa);
+ }
+
+ /* recalculate winakt */
+ getmouseco_sc(mval);
+
+ test_scale_screen(sc);
+ testareas();
+
+ for (sa= sc->areabase.first; sa; sa= sa->next) {
+ SpaceLink *sl;
+
+ for (sl= sa->spacedata.first; sl; sl= sl->next) {
+ sl->area= sa;
+
+ if (sl->spacetype==SPACE_OOPS) {
+ SpaceOops *soops= (SpaceOops*) sl;
+
+ /* patch als deze in oude files zit */
+ if (soops->v2d.cur.xmin==soops->v2d.cur.xmax) {
+ extern void init_v2d_oops(View2D*);
+ init_v2d_oops(&soops->v2d);
+ }
+ }
+ }
+
+ sa->cursor= CURSOR_STD;
+ }
+
+ G.scene= sc->scene;
+ countall();
+
+ G.curscreen->winakt= 0;
+ curarea= sc->areabase.first;
+
+ mainqenter(DRAWEDGES, 1);
+ dodrawscreen= 1; /* patch! even gets lost,,,? */
+
+ winqueue_break= 1; /* overal uit de queue's gaan */
+}
+
+static void splitarea(ScrArea *sa, char dir, float fac);
+
+void area_fullscreen(void) /* met curarea */
+{
+ /* deze funktie toggelt: als area full is wordt de parent weer zichtbaar */
+ bScreen *sc, *oldscreen;
+ ScrArea *newa, *old;
+ short headertype, fulltype;
+
+ if(curarea->full) {
+ sc= curarea->full; /* de oude screen */
+ fulltype = sc->full;
+
+ // refuse to go out of SCREENAUTOPLAY as long as G_FLAGS_AUTOPLAY
+ // is set
+
+ if (fulltype != SCREENAUTOPLAY || (G.flags & G_FLAGS_AUTOPLAY) == 0) {
+ sc->full= 0;
+
+ /* vind oude area */
+ old= sc->areabase.first;
+ while(old) {
+ if(old->full) break;
+ old= old->next;
+ }
+ if(old==0) {error("something wrong in areafullscreen"); return;}
+
+ if (fulltype == SCREENAUTOPLAY) {
+ // in autoplay screens the headers are disabled by
+ // default. So use the old headertype instead
+ headertype = old->headertype;
+ } else {
+ // normal fullscreen. Use current headertype
+ headertype = curarea->headertype;
+ }
+
+ copy_areadata(old, curarea);
+ old->headertype = headertype;
+
+ old->full= 0;
+
+ unlink_screen(G.curscreen);
+ free_libblock(&G.main->screen, G.curscreen);
+ G.curscreen= NULL;
+
+ setscreen(sc);
+ }
+
+ }
+ else {
+ /* is er maar 1 area? */
+ if(G.curscreen->areabase.first==G.curscreen->areabase.last) return;
+ if(curarea->spacetype==SPACE_INFO) return;
+
+ G.curscreen->full = SCREENFULL;
+
+ old= curarea;
+ oldscreen= G.curscreen;
+ sc= addscreen("temp"); /* deze zet G.curscreen */
+
+ splitarea( (ScrArea *)sc->areabase.first, 'h', 0.99);
+ newa= sc->areabase.first;
+ newspace(newa->next, SPACE_INFO);
+
+ curarea= old;
+ G.curscreen= oldscreen; /* moet voor setscreen */
+
+ /* area kopieeren */
+ copy_areadata(newa, curarea);
+
+ curarea->full= oldscreen;
+ newa->full= oldscreen;
+ newa->next->full= oldscreen;
+
+ setscreen(sc);
+ wich_cursor(newa);
+ }
+}
+
+static void area_autoplayscreen(void)
+{
+ bScreen *sc, *oldscreen;
+ ScrArea *newa, *old, *sa;
+
+ if (curarea->full) {
+ area_fullscreen();
+ }
+
+ if (curarea->full == NULL) {
+ sa = G.curscreen->areabase.first;
+ while (sa) {
+ if (sa->spacetype == SPACE_VIEW3D) {
+ break;
+ }
+ sa= sa->next;
+ }
+
+ if (sa) {
+ areawinset(sa->win);
+ G.curscreen->full = SCREENAUTOPLAY;
+
+ old= curarea;
+ oldscreen= G.curscreen;
+ sc= addscreen("temp"); /* deze zet G.curscreen */
+
+ newa= sc->areabase.first;
+
+ curarea= old;
+ G.curscreen= oldscreen; /* moet voor setscreen */
+
+ /* copy area settings */
+ copy_areadata(newa, curarea);
+ newa->headertype= 0;
+
+ curarea->full= oldscreen;
+ newa->full= oldscreen;
+
+ setscreen(sc);
+ wich_cursor(newa);
+ }
+ }
+}
+
+static void copy_screen(bScreen *to, bScreen *from)
+{
+ ScrVert *s1, *s2;
+ ScrEdge *se;
+ ScrArea *sa;
+ ListBase lbase;
+
+ /* alles van to vrijgeven */
+ free_screen(to);
+ winqueue_break= 1; /* overal uit queue's gaan */
+
+ duplicatelist(&to->vertbase, &from->vertbase);
+ duplicatelist(&to->edgebase, &from->edgebase);
+ duplicatelist(&to->areabase, &from->areabase);
+
+ s1= from->vertbase.first;
+ s2= to->vertbase.first;
+ while(s1) {
+ s1->newv= s2;
+ s2= s2->next;
+ s1= s1->next;
+ }
+ se= to->edgebase.first;
+ while(se) {
+ se->v1= se->v1->newv;
+ se->v2= se->v2->newv;
+ sortscrvert(&(se->v1), &(se->v2));
+ se= se->next;
+ }
+
+ sa= to->areabase.first;
+ while(sa) {
+ sa->v1= sa->v1->newv;
+ sa->v2= sa->v2->newv;
+ sa->v3= sa->v3->newv;
+ sa->v4= sa->v4->newv;
+ sa->win= 0;
+ sa->headwin= 0;
+
+ sa->uiblocks.first= sa->uiblocks.last= NULL;
+
+ duplicatespacelist(sa, &lbase, &sa->spacedata);
+ sa->spacedata= lbase;
+
+ sa= sa->next;
+ }
+
+ /* op nul zetten (nodig?) */
+ s1= from->vertbase.first;
+ while(s1) {
+ s1->newv= 0;
+ s1= s1->next;
+ }
+}
+
+void duplicate_screen(void)
+{
+ bScreen *sc, *oldscreen;
+
+ if(G.curscreen->full != SCREENNORMAL) return;
+
+ /* nieuw screen maken: */
+
+ oldscreen= G.curscreen;
+ sc= addscreen(oldscreen->id.name+2); /* deze zet G.curscreen */
+ copy_screen(sc, oldscreen);
+
+ G.curscreen= oldscreen;
+ setscreen(sc);
+
+}
+
+
+/* ************ END SCREENBEHEER ************** */
+/* ************ JOIN/SPLIT/MOVE ************** */
+
+static void joinarea(ScrArea *sa, ScrEdge *onedge)
+{
+ ScrArea *sa2;
+ ScrArea *up=0, *down=0, *right=0, *left=0;
+ ScrEdge *setest;
+ short val=0;
+
+ sa= test_edge_area(sa, onedge);
+ if (sa==0) return;
+
+ /* welke edges kunnen ermee? */
+ /* vind richtingen met zelfde edge */
+ sa2= G.curscreen->areabase.first;
+ while(sa2) {
+ if(sa2 != sa) {
+ setest= screen_findedge(G.curscreen, sa2->v1, sa2->v2);
+ if(onedge==setest) right= sa2;
+ setest= screen_findedge(G.curscreen, sa2->v2, sa2->v3);
+ if(onedge==setest) down= sa2;
+ setest= screen_findedge(G.curscreen, sa2->v3, sa2->v4);
+ if(onedge==setest) left= sa2;
+ setest= screen_findedge(G.curscreen, sa2->v4, sa2->v1);
+ if(onedge==setest) up= sa2;
+ }
+ sa2= sa2->next;
+ }
+
+ sa2= 0;
+ setest= 0;
+
+ if(left) val++;
+ if(up) val++;
+ if(right) val++;
+ if(down) val++;
+
+ if(val==0) return;
+ else if(val==1) {
+ if(left) sa2= left;
+ else if(up) sa2= up;
+ else if(right) sa2= right;
+ else if(down) sa2= down;
+ }
+
+
+ if(sa2) {
+ /* nieuwe area is oude sa */
+ if(sa2==left) {
+ sa->v1= sa2->v1;
+ sa->v2= sa2->v2;
+ screen_addedge(G.curscreen, sa->v2, sa->v3);
+ screen_addedge(G.curscreen, sa->v1, sa->v4);
+ }
+ else if(sa2==up) {
+ sa->v2= sa2->v2;
+ sa->v3= sa2->v3;
+ screen_addedge(G.curscreen, sa->v1, sa->v2);
+ screen_addedge(G.curscreen, sa->v3, sa->v4);
+ }
+ else if(sa2==right) {
+ sa->v3= sa2->v3;
+ sa->v4= sa2->v4;
+ screen_addedge(G.curscreen, sa->v2, sa->v3);
+ screen_addedge(G.curscreen, sa->v1, sa->v4);
+ }
+ else if(sa2==down) {
+ sa->v1= sa2->v1;
+ sa->v4= sa2->v4;
+ screen_addedge(G.curscreen, sa->v1, sa->v2);
+ screen_addedge(G.curscreen, sa->v3, sa->v4);
+ }
+
+ /* edge en area weg */
+ /* remlink(&G.curscreen->edgebase, setest); */
+ /* freeN(setest); */
+ del_area(sa2);
+ BLI_remlink(&G.curscreen->areabase, sa2);
+ MEM_freeN(sa2);
+
+ removedouble_scredges();
+ removenotused_scredges();
+ removenotused_scrverts(); /* moet als laatste */
+
+ testareas();
+ mainqenter(DRAWEDGES, 1);
+ /* test cursor en inputwindow */
+ mainqenter(MOUSEY, -1);
+ }
+}
+
+static short testsplitpoint(ScrArea *sa, char dir, float fac)
+/* return 0: geen split mogelijk */
+/* else return (integer) screencoordinaat splitpunt */
+{
+ short x, y;
+
+ /* area groot genoeg? */
+ if(sa->v4->vec.x- sa->v1->vec.x <= 2*AREAMINX) return 0;
+ if(sa->v2->vec.y- sa->v1->vec.y <= 2*AREAMINY) return 0;
+
+ /* voor zekerheid */
+ if(fac<0.0) fac= 0.0;
+ if(fac>1.0) fac= 1.0;
+
+ if(dir=='h') {
+ y= sa->v1->vec.y+ fac*(sa->v2->vec.y- sa->v1->vec.y);
+
+ if(sa->v2->vec.y==G.curscreen->sizey-1 && sa->v2->vec.y- y < HEADERY+EDGEWIDTH2)
+ y= sa->v2->vec.y- HEADERY-EDGEWIDTH2;
+
+ else if(sa->v1->vec.y==0 && y- sa->v1->vec.y < HEADERY+EDGEWIDTH2)
+ y= sa->v1->vec.y+ HEADERY+EDGEWIDTH2;
+
+ else if(y- sa->v1->vec.y < AREAMINY) y= sa->v1->vec.y+ AREAMINY;
+ else if(sa->v2->vec.y- y < AREAMINY) y= sa->v2->vec.y- AREAMINY;
+ else y-= (y % AREAGRID);
+
+ return y;
+ }
+ else {
+ x= sa->v1->vec.x+ fac*(sa->v4->vec.x- sa->v1->vec.x);
+ if(x- sa->v1->vec.x < AREAMINX) x= sa->v1->vec.x+ AREAMINX;
+ else if(sa->v4->vec.x- x < AREAMINX) x= sa->v4->vec.x- AREAMINX;
+ else x-= (x % AREAGRID);
+
+ return x;
+ }
+}
+
+static void splitarea(ScrArea *sa, char dir, float fac)
+{
+ bScreen *sc;
+ ScrArea *newa;
+ ScrVert *sv1, *sv2;
+ short split;
+
+ if(sa==0) return;
+
+ split= testsplitpoint(sa, dir, fac);
+ if(split==0) return;
+
+ sc= G.curscreen;
+
+ areawinset(sa->win);
+
+ if(dir=='h') {
+ /* nieuwe vertices */
+ sv1= screen_addvert(sc, sa->v1->vec.x, split);
+ sv2= screen_addvert(sc, sa->v4->vec.x, split);
+
+ /* nieuwe edges */
+ screen_addedge(sc, sa->v1, sv1);
+ screen_addedge(sc, sv1, sa->v2);
+ screen_addedge(sc, sa->v3, sv2);
+ screen_addedge(sc, sv2, sa->v4);
+ screen_addedge(sc, sv1, sv2);
+
+ /* nieuwe areas: boven */
+ newa= screen_addarea(sc, sv1, sa->v2, sa->v3, sv2, sa->headertype, sa->spacetype);
+ copy_areadata(newa, sa);
+
+ /* area onder */
+ sa->v2= sv1;
+ sa->v3= sv2;
+
+ }
+ else {
+ /* nieuwe vertices */
+ sv1= screen_addvert(sc, split, sa->v1->vec.y);
+ sv2= screen_addvert(sc, split, sa->v2->vec.y);
+
+ /* nieuwe edges */
+ screen_addedge(sc, sa->v1, sv1);
+ screen_addedge(sc, sv1, sa->v4);
+ screen_addedge(sc, sa->v2, sv2);
+ screen_addedge(sc, sv2, sa->v3);
+ screen_addedge(sc, sv1, sv2);
+
+ /* nieuwe areas: links */
+ newa= screen_addarea(sc, sa->v1, sa->v2, sv2, sv1, sa->headertype, sa->spacetype);
+ copy_areadata(newa, sa);
+
+ /* area rechts */
+ sa->v1= sv1;
+ sa->v2= sv2;
+ }
+
+ /* dubbele vertices en edges verwijderen */
+ removedouble_scrverts();
+ removedouble_scredges();
+ removenotused_scredges();
+
+ mainqenter(DRAWEDGES, 1);
+ dodrawscreen= 1; /* patch! even gets lost,,,? */
+ testareas();
+}
+
+static void scrarea_draw_splitpoint(ScrArea *sa, char dir, float fac)
+{
+ int split= testsplitpoint(sa, dir, fac);
+
+ if (split) {
+ if(dir=='h') {
+ glutil_draw_front_xor_line(sa->totrct.xmin, split, sa->totrct.xmax, split);
+ glutil_draw_front_xor_line(sa->totrct.xmin, split-1, sa->totrct.xmax, split-1);
+ } else {
+ glutil_draw_front_xor_line(split, sa->totrct.ymin, split, sa->totrct.ymax);
+ glutil_draw_front_xor_line(split-1, sa->totrct.ymin, split-1, sa->totrct.ymax);
+ }
+ }
+}
+
+static void splitarea_interactive(ScrArea *area, ScrEdge *onedge)
+{
+ ScrArea *sa= area;
+ float fac;
+ unsigned short event;
+ short ok= 0, val, split = 0, mval[2], mvalo[2], first= 1;
+ char dir;
+
+ if(sa->win==0) return;
+ if(sa->full) return;
+
+ dir= scredge_is_horizontal(onedge)?'v':'h';
+
+ mywinset(G.curscreen->mainwin);
+ /* hoort al goede matrix te hebben */
+
+ /* rekening houden met grid en minsize */
+ while(ok==0) {
+ getmouseco_sc(mval);
+
+ if (first || mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
+ if (!first) {
+ scrarea_draw_splitpoint(sa, dir, fac);
+ }
+
+ if(dir=='h') {
+ fac= mval[1]- (sa->v1->vec.y);
+ fac/= sa->v2->vec.y- sa->v1->vec.y;
+ } else {
+ fac= mval[0]- sa->v1->vec.x;
+ fac/= sa->v4->vec.x- sa->v1->vec.x;
+ }
+
+ split= testsplitpoint(sa, dir, fac);
+ if (split) {
+ scrarea_draw_splitpoint(sa, dir, fac);
+ } else {
+ ok= -1;
+ }
+
+ mvalo[0]= mval[0];
+ mvalo[1]= mval[1];
+ first= 0;
+ }
+
+ event= extern_qread(&val);
+ if(val && event==LEFTMOUSE) {
+ if(dir=='h') {
+ fac= split- (sa->v1->vec.y);
+ fac/= sa->v2->vec.y- sa->v1->vec.y;
+ }
+ else {
+ fac= split- sa->v1->vec.x;
+ fac/= sa->v4->vec.x- sa->v1->vec.x;
+ }
+ ok= 1;
+ }
+ if(val && event==ESCKEY) {
+ ok= -1;
+ }
+ }
+
+ if (!first) {
+ scrarea_draw_splitpoint(sa, dir, fac);
+ }
+
+ if(ok==1) {
+ splitarea(sa, dir, fac);
+ mainqenter(DRAWEDGES, 1);
+ dodrawscreen= 1; /* patch! even gets lost,,,? */
+ }
+}
+
+View3D *find_biggest_view3d(void)
+{
+ ScrArea *sa= find_biggest_area_of_type(SPACE_VIEW3D);
+
+ if (sa) {
+ return (View3D*) sa->spacedata.first;
+ } else {
+ return NULL;
+ }
+}
+
+ScrArea *find_biggest_area_of_type(int spacecode)
+{
+ ScrArea *sa, *biggest= NULL;
+ int bigsize;
+
+ for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
+ if (spacecode==0 || sa->spacetype==spacecode) {
+ int x= sa->v3->vec.x - sa->v1->vec.x;
+ int y= sa->v3->vec.y - sa->v1->vec.y;
+ int size= x*x + y*y;
+
+ if (!biggest || size>bigsize) {
+ biggest= sa;
+ bigsize= size;
+ }
+ }
+ }
+
+ return biggest;
+}
+
+ScrArea *find_biggest_area(void)
+{
+ return find_biggest_area_of_type(0);
+}
+
+static void select_connected_scredge(bScreen *sc, ScrEdge *edge)
+{
+ ScrEdge *se;
+ ScrVert *sv;
+ int oneselected;
+ char dir;
+
+ /* select connected, alleen in de juiste richting */
+ /* 'dir' is de richting van de EDGE */
+
+ if(edge->v1->vec.x==edge->v2->vec.x) dir= 'v';
+ else dir= 'h';
+
+ sv= sc->vertbase.first;
+ while(sv) {
+ sv->flag= 0;
+ sv= sv->next;
+ }
+
+ edge->v1->flag= 1;
+ edge->v2->flag= 1;
+
+ oneselected= 1;
+ while(oneselected) {
+ se= sc->edgebase.first;
+ oneselected= 0;
+ while(se) {
+ if(se->v1->flag + se->v2->flag==1) {
+ if(dir=='h') if(se->v1->vec.y==se->v2->vec.y) {
+ se->v1->flag= se->v2->flag= 1;
+ oneselected= 1;
+ }
+ if(dir=='v') if(se->v1->vec.x==se->v2->vec.x) {
+ se->v1->flag= se->v2->flag= 1;
+ oneselected= 1;
+ }
+ }
+ se= se->next;
+ }
+ }
+}
+
+void test_scale_screen(bScreen *sc)
+/* testen of screenvertices vergroot/verkleind moeten worden */
+/* testen of offset nog klopt */
+{
+ ScrVert *sv=0;
+ ScrEdge *se;
+ ScrArea *sa, *san;
+ int yval;
+ float facx, facy, tempf, min[2], max[2];
+
+ sc->startx= prefstax;
+ sc->starty= prefstay;
+ sc->endx= prefstax+prefsizx-1;
+ sc->endy= prefstay+prefsizy-1;
+
+ /* calculate size */
+ sv= sc->vertbase.first;
+ min[0]= min[1]= 0.0;
+ max[0]= sc->sizex;
+ max[1]= sc->sizey;
+ while(sv) {
+ min[0]= MIN2(min[0], sv->vec.x);
+ min[1]= MIN2(min[1], sv->vec.y);
+ max[0]= MAX2(max[0], sv->vec.x);
+ max[1]= MAX2(max[1], sv->vec.y);
+ sv= sv->next;
+ }
+
+ /* always make 0.0 left under */
+ sv= sc->vertbase.first;
+ while(sv) {
+ sv->vec.x -= min[0];
+ sv->vec.y -= min[1];
+ sv= sv->next;
+ }
+
+
+ sc->sizex= max[0]-min[0];
+ sc->sizey= max[1]-min[1];
+
+ if(sc->sizex!= prefsizx || sc->sizey!= prefsizy) {
+ facx= prefsizx;
+ facx/= (float)sc->sizex;
+ facy= prefsizy;
+ facy/= (float)sc->sizey;
+
+ /* make sure it fits! */
+ sv= sc->vertbase.first;
+ while(sv) {
+ tempf= ((float)sv->vec.x)*facx;
+ sv->vec.x= (short)(tempf+0.5);
+ sv->vec.x+= AREAGRID-1;
+ sv->vec.x-= (sv->vec.x % AREAGRID);
+
+ CLAMP(sv->vec.x, 0, prefsizx);
+
+ tempf= ((float)sv->vec.y )*facy;
+ sv->vec.y= (short)(tempf+0.5);
+ sv->vec.y+= AREAGRID-1;
+ sv->vec.y-= (sv->vec.y % AREAGRID);
+
+ CLAMP(sv->vec.y, 0, prefsizy);
+
+ sv= sv->next;
+ }
+
+ sc->sizex= prefsizx;
+ sc->sizey= prefsizy;
+ }
+
+ /* test for collapsed areas. This could happen in some blender version... */
+ sa= sc->areabase.first;
+ while(sa) {
+ san= sa->next;
+ if(sa->v1==sa->v2 || sa->v3==sa->v4 || sa->v2==sa->v3) {
+ del_area(sa);
+ BLI_remlink(&sc->areabase, sa);
+ MEM_freeN(sa);
+ }
+ sa= san;
+ }
+
+ /* make each window at least HEADERY high */
+
+ sa= sc->areabase.first;
+ while(sa) {
+
+ if(sa->v1->vec.y+HEADERY > sa->v2->vec.y) {
+ /* lower edge */
+ se= screen_findedge(sc, sa->v4, sa->v1);
+ if(se && sa->v1!=sa->v2 ) {
+ select_connected_scredge(sc, se);
+
+ /* all selected vertices get the right offset */
+ yval= sa->v2->vec.y-HEADERY;
+ sv= sc->vertbase.first;
+ while(sv) {
+ /* if is a collapsed area */
+ if(sv!=sa->v2 && sv!=sa->v3) {
+ if(sv->flag) sv->vec.y= yval;
+ }
+ sv= sv->next;
+ }
+ }
+ }
+
+ sa= sa->next;
+ }
+
+}
+
+static void draw_front_xor_dirdist_line(char dir, int dist, int start, int end)
+{
+ if (dir=='h') {
+ glutil_draw_front_xor_line(start, dist, end, dist);
+ glutil_draw_front_xor_line(start, dist+1, end, dist+1);
+ } else {
+ glutil_draw_front_xor_line(dist, start, dist, end);
+ glutil_draw_front_xor_line(dist+1, start, dist+1, end);
+ }
+}
+
+static void moveareas(ScrEdge *edge)
+{
+ ScrVert *v1;
+ ScrArea *sa;
+ short mvalo[2];
+ short edge_start, edge_end, edge_position;
+ short bigger, smaller, headery, areaminy;
+ int delta, doit;
+ char dir;
+
+ if(edge->border) return;
+
+ dir= scredge_is_horizontal(edge)?'h':'v';
+
+ select_connected_scredge(G.curscreen, edge);
+
+ edge_position= (dir=='h')?edge->v1->vec.y:edge->v1->vec.x;
+ edge_start= 10000;
+ edge_end= -10000;
+ for (v1= G.curscreen->vertbase.first; v1; v1= v1->next) {
+ if (v1->flag) {
+ if (dir=='h') {
+ edge_start= MIN2(edge_start, v1->vec.x);
+ edge_end= MAX2(edge_end, v1->vec.x);
+ } else {
+ edge_start= MIN2(edge_start, v1->vec.y);
+ edge_end= MAX2(edge_end, v1->vec.y);
+ }
+ }
+ }
+
+ /* nu zijn alle vertices met 'flag==1' degene die verplaatst kunnen worden. */
+ /* we lopen de areas af en testen vrije ruimte met MINSIZE */
+ bigger= smaller= 10000;
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(dir=='h') { /* als top of down edge select, test hoogte */
+ if(sa->headertype) {
+ headery= HEADERY;
+ areaminy= AREAMINY;
+ }
+ else {
+ headery= 0;
+ areaminy= EDGEWIDTH;
+ }
+
+ if(sa->v1->flag && sa->v4->flag) {
+ int y1;
+ if(sa->v2->vec.y==G.curscreen->sizey-1) /* bovenste edge */
+ y1= sa->v2->vec.y - sa->v1->vec.y-headery-EDGEWIDTH;
+ else
+ y1= sa->v2->vec.y - sa->v1->vec.y-areaminy;
+ bigger= MIN2(bigger, y1);
+ }
+ else if(sa->v2->flag && sa->v3->flag) {
+ int y1;
+ if(sa->v1->vec.y==0) /* onderste edge */
+ y1= sa->v2->vec.y - sa->v1->vec.y-headery-EDGEWIDTH;
+ else
+ y1= sa->v2->vec.y - sa->v1->vec.y-areaminy;
+ smaller= MIN2(smaller, y1);
+ }
+ }
+ else { /* als left of right edge select, test breedte */
+ if(sa->v1->flag && sa->v2->flag) {
+ int x1= sa->v4->vec.x - sa->v1->vec.x-AREAMINX;
+ bigger= MIN2(bigger, x1);
+ }
+ else if(sa->v3->flag && sa->v4->flag) {
+ int x1= sa->v4->vec.x - sa->v1->vec.x-AREAMINX;
+ smaller= MIN2(smaller, x1);
+ }
+ }
+ sa= sa->next;
+ }
+
+ mywinset(G.curscreen->mainwin);
+
+ doit= delta= 0;
+ getmouseco_sc(mvalo);
+ draw_front_xor_dirdist_line(dir, edge_position+delta, edge_start, edge_end);
+ while (!doit) {
+ short val;
+ unsigned short event= extern_qread(&val);
+
+ if (event==MOUSEY) {
+ short mval[2];
+
+ getmouseco_sc(mval);
+
+ draw_front_xor_dirdist_line(dir, edge_position+delta, edge_start, edge_end);
+
+ delta= (dir=='h')?(mval[1]-mvalo[1]):(mval[0]-mvalo[0]);
+ delta= CLAMPIS(delta, -smaller, bigger);
+
+ draw_front_xor_dirdist_line(dir, edge_position+delta, edge_start, edge_end);
+ } else if (event==LEFTMOUSE) {
+ doit= 1;
+ } else if (val) {
+ if (ELEM(event, ESCKEY, RIGHTMOUSE))
+ doit= -1;
+ else if (ELEM(event, SPACEKEY, RETKEY))
+ doit= 1;
+ }
+ }
+ draw_front_xor_dirdist_line(dir, edge_position+delta, edge_start, edge_end);
+
+ if (doit==1) {
+ for (v1= G.curscreen->vertbase.first; v1; v1= v1->next) {
+ if (v1->flag) {
+ /* zo is AREAGRID netjes */
+ if((dir=='v') && v1->vec.x>0 && v1->vec.x<G.curscreen->sizex-1) {
+ v1->vec.x+= delta;
+ if(delta != bigger && delta != -smaller) v1->vec.x-= (v1->vec.x % AREAGRID);
+ }
+ if((dir=='h') && v1->vec.y>0 && v1->vec.y<G.curscreen->sizey-1) {
+ v1->vec.y+= delta;
+
+ /* with these lines commented out you can pull the top bar exact to the screen border. */
+ /* if(delta != bigger && delta != -smaller) { */
+ v1->vec.y+= AREAGRID-1;
+ v1->vec.y-= (v1->vec.y % AREAGRID);
+
+ /* } */
+ }
+ }
+ v1->flag= 0;
+ }
+
+ removedouble_scrverts();
+ removedouble_scredges();
+ testareas();
+ }
+
+ glDrawBuffer(GL_BACK);
+ mainqenter(DRAWEDGES, 1);
+ dodrawscreen= 1; /* patch! even gets lost,,,? */
+}
+
+static void scrollheader(ScrArea *area)
+{
+ short mval[2], mvalo[2];
+
+ if(area->headbutlen<area->winx) {
+ area->headbutofs= 0;
+ }
+ else if(area->headbutofs+area->winx > area->headbutlen) {
+ area->headbutofs= area->headbutlen-area->winx;
+ }
+
+ getmouseco_sc(mvalo);
+
+ while(get_mbut() & M_MOUSE) {
+ getmouseco_sc(mval);
+ if(mval[0]!=mvalo[0]) {
+ area->headbutofs-= (mval[0]-mvalo[0]);
+
+ if(area->headbutlen-area->winx < area->headbutofs) area->headbutofs= area->headbutlen-area->winx;
+ if(area->headbutofs<0) area->headbutofs= 0;
+
+ scrarea_do_headchange(area);
+ scrarea_do_headdraw(area);
+
+ screen_swapbuffers();
+
+ mvalo[0]= mval[0];
+ } else {
+ BIF_wait_for_statechange();
+ }
+ }
+}
+
+int select_area(int spacetype)
+{
+ /* vanuit editroutines aanroepen, als er meer area's
+ * zijn van type 'spacetype' kan er een area aangegeven worden
+ */
+ ScrArea *sa, *sact = NULL;
+ int tot=0;
+ unsigned short event = 0;
+ short val, mval[2];
+
+ sa= G.curscreen->areabase.first;
+ while(sa) {
+ if(sa->spacetype==spacetype) {
+ sact= sa;
+ tot++;
+ }
+ sa= sa->next;
+ }
+
+ if(tot==0) {
+ error("Can't do this! Open correct window");
+ return 0;
+ }
+
+ if(tot==1) {
+ if(curarea!=sact) areawinset(sact->win);
+ return 1;
+ }
+ else if(tot>1) {
+ set_cursor(CURSOR_HELP);
+ while(1) {
+ event= extern_qread(&val);
+
+ if (val) {
+ if(event==ESCKEY) break;
+ if(event==LEFTMOUSE) break;
+ if(event==SPACEKEY) break;
+ } else {
+ BIF_wait_for_statechange();
+ }
+ }
+ screen_set_cursor(G.curscreen);
+
+ /* recalculate winakt */
+ getmouseco_sc(mval);
+
+ if(event==LEFTMOUSE) {
+ ScrArea *sa= screen_find_area_for_pt(G.curscreen, mval);
+
+ if (sa &&sa->spacetype==spacetype) {
+ G.curscreen->winakt= sa->win;
+ areawinset(G.curscreen->winakt);
+ } else {
+ error("wrong window");
+ return 0;
+ }
+ }
+ }
+
+ if(event==LEFTMOUSE) return 1;
+ else return 0;
+}
+
+/* ************ END JOIN/SPLIT/MOVE ************** */
+/* **************** DRAW SCREENEDGES ***************** */
+
+#define EDGE_EXTEND 3
+
+void drawedge(short x1, short y1, short x2, short y2)
+{
+ static unsigned int edcol[EDGEWIDTH]= {0x0, 0x505050, 0x909090, 0xF0F0F0, 0x0};
+ int a;
+
+ if(x1==x2) { /* vertical */
+ if (y2<y1)
+ y1^= y2^= y1^= y2;
+
+ if (y1==0) y1-= EDGE_EXTEND;
+ if (y2==G.curscreen->sizey) y2+= EDGE_EXTEND;
+
+ x1+= EDGEWIDTH2;
+ x2+= EDGEWIDTH2;
+
+ glBegin(GL_LINES);
+ for(a=0; a<EDGEWIDTH; a++) {
+ int rounding= abs(a-EDGEWIDTH2);
+
+ cpack(edcol[a]);
+ glVertex2i(x1-a, y1+rounding);
+ glVertex2i(x2-a, y2-rounding);
+ }
+ glEnd();
+ }
+ else { /* horizontal */
+ if (x2<x1)
+ x1^= x2^= x1^= x2;
+
+ if (x1==0) x1-= EDGE_EXTEND;
+ if (x2==G.curscreen->sizex) x2+= EDGE_EXTEND;
+
+ y1-= EDGEWIDTH2;
+ y2-= EDGEWIDTH2;
+
+ glBegin(GL_LINES);
+ for(a=0; a<EDGEWIDTH; a++) {
+ int rounding= abs(a-EDGEWIDTH2);
+
+ cpack(edcol[a]);
+ glVertex2i(x1+rounding, y1+a);
+ glVertex2i(x2-rounding, y2+a);
+ }
+ glEnd();
+ }
+}
+
+static void drawscredge(ScrEdge *se)
+{
+ bScreen *sc;
+ vec2s *v1, *v2;
+
+ sc= G.curscreen;
+
+ v1= &(se->v1->vec);
+ v2= &(se->v2->vec);
+
+ /* borders screen niet tekenen */
+ /* vanwege resolutie verschillen (PC/SGI files) de linit een
+ * beetje afronden?
+ */
+ se->border= 1;
+ if(v1->x<=1 && v2->x<=1) return;
+ if(v1->x>=sc->sizex-2 && v2->x>=sc->sizex-2) return;
+ if(v1->y<=1 && v2->y<=1) return;
+ if(v1->y>=sc->sizey-2 && v2->y>=sc->sizey-2) return;
+ se->border= 0;
+
+ drawedge(v1->x, v1->y, v2->x, v2->y);
+}
+
+void drawscreen(void)
+{
+ ScrEdge *se;
+
+ mywinset(G.curscreen->mainwin);
+ myortho2(-0.5, (float)G.curscreen->sizex-0.5, -0.5, (float)G.curscreen->sizey-0.5);
+
+ /* two times, because there is no 'win_swap' for this available */
+ glDrawBuffer(GL_FRONT);
+ se= G.curscreen->edgebase.first;
+ while(se) {
+ drawscredge(se);
+ se= se->next;
+ }
+
+ glDrawBuffer(GL_BACK);
+ se= G.curscreen->edgebase.first;
+ while(se) {
+ drawscredge(se);
+ se= se->next;
+ }
+}
+
+/* ********************************* */
+
+bScreen *default_twosplit()
+{
+ bScreen *sc= addscreen("screen");
+ ScrArea *sa;
+
+ splitarea( (ScrArea *)sc->areabase.first, 'h', 0.99);
+ sa= sc->areabase.first;
+ newspace(sa, SPACE_VIEW3D);
+ newspace(sa->next, SPACE_INFO);
+
+ return sc;
+}
+
+void initscreen(void)
+{
+ default_twosplit();
+}
+
+/***/
+
+void screen_draw_info_text(bScreen *sc, char *text) {
+ Window *oldactwin= winlay_get_active_window();
+ ScrArea *sa;
+
+ /*
+ * Because this is called from within rendering
+ * internals it is possible our window is not
+ * active.
+ */
+ window_make_active(mainwin);
+
+ for (sa= sc->areabase.first; sa; sa= sa->next) {
+ if (sa->spacetype==SPACE_INFO) {
+ int x= sa->headbutlen - 28;
+ int y= 6;
+
+ areawinset(sa->headwin);
+ glDrawBuffer(GL_FRONT);
+
+ cpack(0xA08060);
+ glRecti(x-11, y-6, x+55, y+13);
+
+ cpack(0x909090);
+ glRecti(x+55, y-6, x+1280, y+14);
+
+ cpack(0x0);
+ glRasterPos2i(x, y);
+ BMF_DrawString(G.fonts, text);
+
+ glFinish();
+ glDrawBuffer(GL_BACK);
+
+ sa->head_swap= WIN_FRONT_OK;
+ }
+ }
+
+ if (oldactwin && oldactwin!=mainwin) window_make_active(oldactwin);
+}
+
+static int curcursor;
+
+int get_cursor(void) {
+ return curcursor;
+}
+
+void set_cursor(int curs) {
+ if (!(R.flag & R_RENDERING)) {
+ if (curs!=curcursor) {
+ curcursor= curs;
+ window_set_cursor(mainwin, curs);
+ }
+ }
+}
+
+void unlink_screen(bScreen *sc) {
+ ScrArea *sa;
+
+ for (sa= sc->areabase.first; sa; sa= sa->next)
+ del_area(sa);
+}
+
+void warp_pointer(int x, int y)
+{
+ window_warp_pointer(mainwin, x, y);
+}
+
+void set_timecursor(int nr)
+{
+ /* 10 8x8 digits */
+ static char number_bitmaps[10][8]= {
+ {0, 56, 68, 68, 68, 68, 68, 56},
+ {0, 24, 16, 16, 16, 16, 16, 56},
+ {0, 60, 66, 32, 16, 8, 4, 126},
+ {0, 124, 32, 16, 56, 64, 66, 60},
+ {0, 32, 48, 40, 36, 126, 32, 32},
+ {0, 124, 4, 60, 64, 64, 68, 56},
+ {0, 56, 4, 4, 60, 68, 68, 56},
+ {0, 124, 64, 32, 16, 8, 8, 8},
+ {0, 60, 66, 66, 60, 66, 66, 60},
+ {0, 56, 68, 68, 120, 64, 68, 56}
+ };
+ unsigned char mask[16][2];
+ unsigned char bitmap[16][2];
+ int i, idx;
+
+ memset(&bitmap, 0x00, sizeof(bitmap));
+ memset(&mask, 0xFF, sizeof(mask));
+
+ /* print number bottom right justified */
+ for (idx= 3; nr && idx>=0; idx--) {
+ char *digit= number_bitmaps[nr%10];
+ int x = idx%2;
+ int y = idx/2;
+
+ for (i=0; i<8; i++)
+ bitmap[i + y*8][x]= digit[i];
+ nr/= 10;
+ }
+
+ curcursor= CURSOR_NONE;
+ window_set_custom_cursor(mainwin, mask, bitmap);
+ BIF_renderwin_set_custom_cursor(mask, bitmap);
+}
+