4f4cd263c15e291119e844fc78d8ff395d82bd1c
[blender.git] / source / blender / src / editscreen.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  * All screen functions that are related to the interface
32  * handling and drawing. Might be split up as well later...
33  */
34
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38
39 #ifdef WIN32
40 #include "BLI_winstuff.h"
41 #endif   
42
43 #include "nla.h"
44
45 #include <stdlib.h>
46 #include <string.h>
47 #include <stdio.h>
48 #include <math.h>
49
50 #include "MEM_guardedalloc.h"
51
52 #include "PIL_time.h"
53
54 #include "BMF_Api.h"
55
56 #include "BLI_blenlib.h"
57 #include "BLI_arithb.h"
58
59 #include "IMB_imbuf_types.h"
60 #include "IMB_imbuf.h"
61
62 #include "DNA_action_types.h"
63 #include "DNA_object_types.h"
64 #include "DNA_screen_types.h"
65 #include "DNA_space_types.h"
66 #include "DNA_sound_types.h"
67 #include "DNA_view3d_types.h"
68 #include "DNA_userdef_types.h"
69
70 #include "BLO_writefile.h"
71
72 #include "BKE_utildefines.h"
73 #include "BKE_global.h"
74 #include "BKE_library.h"
75 #include "BKE_main.h"
76 #include "BKE_blender.h"
77 #include "BKE_screen.h"
78
79 #include "BIF_editsound.h"
80 #include "BIF_glutil.h"
81 #include "BIF_gl.h"
82 #include "BIF_graphics.h"
83 #include "BIF_interface.h"
84 #include "BIF_mainqueue.h"
85 #include "BIF_mywindow.h"
86 #include "BIF_renderwin.h"
87 #include "BIF_screen.h"
88 #include "BIF_space.h"
89 #include "BIF_toets.h"
90 #include "BIF_toolbox.h"
91 #include "BIF_usiblender.h"
92 #include "BIF_keyval.h"
93
94 #include "BSE_edit.h"
95 #include "BSE_filesel.h"
96 #include "BSE_headerbuttons.h"
97 #include "BSE_view.h"
98
99 #include "interface.h"
100 #include "mydevice.h"
101 #include "blendef.h"
102 #include "render.h"
103
104 #include "winlay.h"
105
106 /* TIPS:
107  * 
108  * - LET OP DE EDGES,  VERTICES ERVAN MOETEN IN VOLGORDE
109          (laagste pointer eerst). Anders onvoorspelbare effecten!
110  * - probleem: flags zijn nog niet echt netjes. Altijd na gebruik
111          op nul zetten.
112  */
113
114 static void testareas(void);
115 static void area_autoplayscreen(void);
116 static void wait_for_event(void);
117
118 /* ********* Globals *********** */
119
120 static Window *mainwin= NULL;
121 static int prefsizx= 0, prefsizy= 0, prefstax= 0, prefstay= 0, start_maximized= 1;
122 static short dodrawscreen= 0;
123 static ScrArea *areawinar[MAXWIN];
124 static ScrArea *g_activearea= NULL;
125 short winqueue_break= 0;
126 ScrArea *curarea= 0;
127
128 /**********************************************************************/
129
130 static void screen_set_cursor(bScreen *sc) 
131 {
132         if (sc->winakt>3) {
133                 ScrArea *sa= areawinar[sc->winakt];
134
135                 set_cursor(sa->cursor);
136         } else {
137                 set_cursor(CURSOR_STD);
138         }
139 }
140
141 void waitcursor(int val)
142 {
143         if(val) {
144                 set_cursor(CURSOR_WAIT);
145         } else {
146                 screen_set_cursor(G.curscreen);
147         }
148 }
149
150 static int choose_cursor(ScrArea *sa)
151 {
152         if (sa->spacetype==SPACE_VIEW3D) {
153                 if(G.obedit) return CURSOR_EDIT;
154                 else if(G.f & G_VERTEXPAINT) return CURSOR_VPAINT;
155                 else if(G.f & G_WEIGHTPAINT) return CURSOR_VPAINT;
156                 else if(G.f & G_FACESELECT) return CURSOR_FACESEL;
157                 else return CURSOR_STD;
158         } else {
159                 return CURSOR_STD;
160         }
161 }
162
163 void wich_cursor(ScrArea *sa)
164 {
165         sa->cursor= choose_cursor(sa);
166
167         screen_set_cursor(G.curscreen);
168 }
169
170
171 void setcursor_space(int spacetype, short cur)
172 {
173         bScreen *sc;
174         ScrArea *sa;
175
176         for (sc= G.main->screen.first; sc; sc= sc->id.next)
177                 for (sa= sc->areabase.first; sa; sa= sa->next)
178                         if(sa->spacetype==spacetype)
179                                 sa->cursor= cur;
180
181         screen_set_cursor(G.curscreen);
182 }
183
184
185 /* *********  IN/OUT  ************* */
186
187 void getmouseco_sc(short *mval)         /* screen coordinaten */
188 {
189         getmouse(mval);
190 }
191
192 void getmouseco_areawin(short *mval)            /* interne area coordinaten */
193 {
194         getmouseco_sc(mval);
195         
196         if(g_activearea && g_activearea->win) {
197                 mval[0]-= g_activearea->winrct.xmin;
198                 mval[1]-= g_activearea->winrct.ymin;
199         }
200 }
201
202 void getmouseco_headwin(short *mval)            /* interne area coordinaten */
203 {
204         getmouseco_sc(mval);
205         
206         if(g_activearea && g_activearea->headwin) {
207                 mval[0]-= g_activearea->headrct.xmin;
208                 mval[1]-= g_activearea->headrct.ymin;
209         }
210 }
211
212 /* *********** STUFF ************** */
213
214 static int scredge_is_horizontal(ScrEdge *se)
215 {
216         return (se->v1->vec.y == se->v2->vec.y);
217 }
218
219 static ScrEdge *screen_find_active_scredge(bScreen *sc, short *mval)
220 {
221         ScrEdge *se;
222         
223         for (se= sc->edgebase.first; se; se= se->next) {
224                 if (scredge_is_horizontal(se)) {
225                         if (abs(mval[1]-se->v1->vec.y)<=EDGEWIDTH2 &&
226                                         abs(mval[0]-se->v1->vec.x)<=abs(se->v2->vec.x-se->v1->vec.x))
227                                 return se;
228                 } else {
229                         if (abs(mval[0]-se->v1->vec.x)<=EDGEWIDTH2 &&
230                                         abs(mval[1]-se->v1->vec.y)<=abs(se->v2->vec.y-se->v1->vec.y))
231                                 return se;
232                 }
233         }
234         
235         return NULL;
236 }
237
238 void areawinset(short win)
239 {
240         if(win>3) {
241                 curarea= areawinar[win];
242                 if(curarea==0) {
243                         printf("error in areawinar %d ,areawinset\n", win);
244                         return;
245                 }
246                 
247                 switch(curarea->spacetype) {
248                 case SPACE_VIEW3D:
249                         G.vd= curarea->spacedata.first;
250                         break;
251                 case SPACE_IPO:
252                         if(G.sipo != curarea->spacedata.first) allqueue(REDRAWBUTSANIM, 0);
253                         G.sipo= curarea->spacedata.first;
254                         G.v2d= &G.sipo->v2d;
255                         break;
256                 case SPACE_BUTS:
257                         G.buts= curarea->spacedata.first;
258                         G.v2d= &G.buts->v2d;
259                         break;
260                 case SPACE_SEQ: {
261                         SpaceSeq *sseq= curarea->spacedata.first;
262                         G.v2d= &sseq->v2d;
263                         break;
264                 }
265                 case SPACE_OOPS:
266                         G.soops= curarea->spacedata.first;
267                         G.v2d= &G.soops->v2d;
268                         break;
269                 case SPACE_IMAGE:
270                         G.sima= curarea->spacedata.first;
271                         G.v2d= &G.sima->v2d;
272                 case SPACE_SOUND:
273                         G.ssound= curarea->spacedata.first;
274                         G.v2d= &G.ssound->v2d;
275                         break;
276                 case SPACE_ACTION:
277                         G.saction= curarea->spacedata.first;
278                         G.v2d= &G.saction->v2d;
279                         break;
280                 case SPACE_NLA:
281                         G.snla= curarea->spacedata.first;
282                         G.v2d= &G.snla->v2d;
283                         break;
284                 default:
285                         break;
286                 }
287         }
288         
289         if(win) mywinset(win);
290 }
291
292 void headerbox(int selcol, int width)
293 {
294         if(selcol) glClearColor(.75, .75, .75, 0.0);
295         else glClearColor(.65, .65, .65, 0.0);
296         
297         glClear(GL_COLOR_BUFFER_BIT);
298
299         glColor3ub(0, 0, 0);
300         sdrawbox(0,  0,  width,  HEADERY);
301
302         glColor3ub(220, 220, 220);
303         sdrawline(0,  HEADERY-1,  width,  HEADERY-1);
304         
305         glColor3ub(176, 176, 176);
306         sdrawline(0,  HEADERY-2,  width,  HEADERY-2);
307         
308         glColor3ub(128, 128, 128);
309         sdrawline(0,  2,  width,  2);
310         
311         glColor3ub(64, 64, 64);
312         sdrawline(0,  1,  width,  1);
313         
314         glColor3ub(0, 0, 0);
315         sdrawline(0,  0,  width,  0);
316 }
317
318 int area_is_active_area(ScrArea *area)
319 {
320         return (g_activearea && area==g_activearea);
321 }
322
323 void scrarea_do_headdraw(ScrArea *area)
324 {
325         areawinset(area->headwin);
326
327         headerbox(area_is_active_area(area), area->winx+100);
328
329         switch(area->spacetype) {
330         case SPACE_FILE:        file_buttons();         break;
331         case SPACE_INFO:        info_buttons();         break;
332         case SPACE_VIEW3D:      view3d_buttons();       break;
333         case SPACE_IPO:         ipo_buttons();          break;
334         case SPACE_BUTS:        buts_buttons();         break;
335         case SPACE_SEQ:         seq_buttons();          break;
336         case SPACE_IMAGE:       image_buttons();        break;
337         case SPACE_IMASEL:      imasel_buttons();       break;
338         case SPACE_OOPS:        oops_buttons();         break;
339         case SPACE_TEXT:        text_buttons();         break;
340         case SPACE_SOUND:       sound_buttons();        break;
341         case SPACE_ACTION:      action_buttons();       break;
342         case SPACE_NLA:         nla_buttons();          break;
343         }
344
345         area->head_swap= WIN_BACK_OK;
346 }
347 void scrarea_do_headchange(ScrArea *area)
348 {
349         float ofs= area->headbutofs;
350
351         if (area->headertype==HEADERDOWN) {
352                 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);
353         } else {
354                 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);
355         }
356 }
357
358
359 static void openheadwin(ScrArea *sa);
360 static void closeheadwin(ScrArea *sa);
361
362 static void scrarea_change_headertype(ScrArea *sa, int newtype) 
363 {
364         sa->headertype= newtype;
365
366         if (!newtype) {
367                 if (sa->headwin) {
368                         uiFreeBlocksWin(&sa->uiblocks, sa->headwin);
369                         closeheadwin(sa);
370                 }
371         } else {
372                 if (!sa->headwin) {
373                         openheadwin(sa);
374                 }
375         }
376
377         testareas();
378         winqueue_break= 1;
379 }
380
381 static void headmenu(ScrArea *sa)
382 {
383         short val= pupmenu("Header %t|Top%x2|Bottom %x1|No Header %x0");
384         
385         if(val> -1) {
386                 scrarea_change_headertype(sa, val);
387         }
388 }
389
390 static void addqueue_ext(short win, unsigned short event, short val, char ascii)
391 {
392         if (win<4 || !areawinar[win]) {
393                 printf("bad call to addqueue: %d (%d, %d)\n", win, event, val);
394         } else {
395                 bwin_qadd(win, event, val, ascii);
396         }
397 }
398
399 void addqueue(short win, unsigned short event, short val)
400 {
401         addqueue_ext(win, event, val, 0);
402 }
403
404 void scrarea_queue_winredraw(ScrArea *area)
405 {
406         addqueue(area->win, REDRAW, 1);
407 }
408 void scrarea_queue_headredraw(ScrArea *area)
409 {
410         if (area->headwin) addqueue(area->headwin, REDRAW, 1);
411 }
412 void scrarea_queue_redraw(ScrArea *area)
413 {
414         scrarea_queue_winredraw(area);
415         scrarea_queue_headredraw(area);
416 }
417
418 static void scrollheader(ScrArea *area);
419 static void scrarea_dispatch_header_events(ScrArea *sa)
420 {
421         ScrArea *tempsa;
422         short do_redraw=0, do_change=0;
423         
424         areawinset(sa->headwin);
425         
426         while(bwin_qtest(sa->headwin)) {
427                 char ascii;
428                 short val;
429                 unsigned short event= bwin_qread(sa->headwin, &val, &ascii);
430
431                 if(val) {
432                         if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
433
434                         switch(event) {
435                         case UI_BUT_EVENT:
436                                 do_headerbuttons(val);
437                                 break;
438                         
439                         case LEFTMOUSE:
440                                 if (G.qual & LR_CTRLKEY) {
441                                         window_lower(mainwin);
442                                 } else {
443                                         window_raise(mainwin);
444                                 }
445                                 break;
446
447                         case MIDDLEMOUSE:
448                                 scrollheader(sa);
449                                 break;
450                         case RIGHTMOUSE:
451                                 headmenu(sa);
452                                 break;
453                         case REDRAW:
454                                 do_redraw= 1;
455                                 break;
456                         case CHANGED:
457                                 sa->head_swap= 0;
458                                 do_change= 1;
459                                 do_redraw= 1;
460                                 break;
461                         default:
462                                 if (winqueue_break == 0) {
463                                         scrarea_do_winhandle(sa, event, val, ascii);
464                                         if (winqueue_break == 0) areawinset(sa->headwin);
465                                 }
466                         }
467                         
468                         if(winqueue_break) return;
469                 }
470         }
471
472         /* test: bestaat window nog */  
473         tempsa= areawinar[sa->headwin];
474         if(tempsa==0) return;
475         
476         /* dit onderscheid loopt niet lekker... */
477         if(do_change) scrarea_do_headchange(sa);
478         if(do_redraw) scrarea_do_headdraw(sa);
479 }
480
481 static void scrarea_dispatch_events(ScrArea *sa)
482 {
483         ScrArea *tempsa;
484         short do_redraw=0, do_change=0;
485         
486         if(sa!=curarea || sa->win!=mywinget()) areawinset(sa->win);
487
488         while(bwin_qtest(sa->win)) {
489                 char ascii;
490                 short val;
491                 unsigned short event= bwin_qread(sa->win, &val, &ascii);
492                 
493                 if(event==REDRAW) {
494                         do_redraw= 1;
495                 }
496                 else if(event==CHANGED) {
497                         sa->win_swap= 0;
498                         do_change= 1;
499                         do_redraw= 1;
500                 }
501                 else {
502                         scrarea_do_winhandle(sa, event, val, ascii);
503                 }
504                 
505                 if(winqueue_break) return;
506         }
507
508         /* test: bestaat window nog */  
509         tempsa= areawinar[sa->win];
510         if(tempsa==0) return;
511
512         if (do_change || do_redraw) {
513                 areawinset(sa->win);
514                 if(do_change)
515                         scrarea_do_winchange(curarea);
516                 if(do_redraw)
517                         scrarea_do_windraw(curarea);
518         }
519 }
520
521 /***/
522
523
524 void markdirty_all()
525 {
526         ScrArea *sa;
527
528         for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
529                 scrarea_queue_winredraw(sa);
530                 sa->win_swap &= ~WIN_FRONT_OK;
531                 
532                 scrarea_queue_headredraw(sa);
533                 sa->head_swap &= ~WIN_FRONT_OK;
534         }
535 }
536
537 int is_allowed_to_change_screen(bScreen *new)
538 {
539         /* niet als curscreen is full
540          * niet als obedit && old->scene!=new->scene
541          */
542         
543         if(new==0) return 0;
544         if(G.curscreen->full != SCREENNORMAL) return 0;
545         if(curarea->full) return 0;
546         if(G.obedit) {
547                 if(G.curscreen->scene!=new->scene) return 0;
548         }
549         return 1;
550 }
551
552 void splash(void *data, int datasize, char *string)
553 {
554         ImBuf *bbuf;
555         int oldwin;
556         short val;
557
558         bbuf= IMB_ibImageFromMemory((int *)data, datasize, IB_rect);
559
560         if (bbuf) {
561
562                 oldwin = mywinget();
563                 mywinset(G.curscreen->mainwin);
564                 
565                 if (string) {
566                         int x, y, maxy;
567                         unsigned int *rect;
568                         
569                         rect = bbuf->rect;
570                         maxy = MIN2(bbuf->y, 18);
571
572                         for (y = 0; y < maxy; y++) {
573                                 for (x = 0; x < bbuf->x; x++) {
574                                         *rect = 0xffffffff;
575                                         rect++;
576                                 }
577                         }
578                 }
579                 glDrawBuffer(GL_FRONT);
580                 
581                 /*
582                 // this dims the whole screen a bit. I didn't like it afterall
583                 glEnable(GL_BLEND);
584                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
585                 glColor4f(0.0,0.0,0.0,0.3);
586                 glRecti(0, 0, G.curscreen->sizex, G.curscreen->sizey);
587                 glDisable(GL_BLEND);
588                 */
589                 
590                 glRasterPos2i((prefsizx-bbuf->x)/2, (prefsizy-bbuf->y)/2);      
591                 glDrawPixels(bbuf->x, bbuf->y, GL_RGBA, GL_UNSIGNED_BYTE, bbuf->rect);
592
593                 if (string) {
594                         void *font;
595                         int width;                      
596                         
597                         if (BMF_GetStringWidth(font= G.font, string) > bbuf->x)
598                                 if (BMF_GetStringWidth(font= G.fonts, string) > bbuf->x)
599                                         font= G.fontss;
600                         
601                         width= BMF_GetStringWidth(font, string);
602                                                 
603                         glColor3ub(0, 0, 0);
604                         glRasterPos2i((prefsizx-width)/2, (prefsizy-bbuf->y)/2 + 6);
605                         BMF_DrawString(font, string);
606                 }
607
608                 glFinish();
609                 glDrawBuffer(GL_BACK);
610                 
611                 IMB_freeImBuf(bbuf);
612                 
613                 // flush input buffers ....
614                 // this might break some things
615
616                 while (get_mbut()) {
617                         BIF_wait_for_statechange();
618                 }
619                 while(qtest()) {
620                         extern_qread(&val);
621                 }
622
623                 wait_for_event();
624                 
625                 mywinset(oldwin);
626                 markdirty_all();
627                 mainqenter(DRAWEDGES, 1);
628         }
629 }
630
631 static void moveareas(ScrEdge *edge);
632 static void joinarea(ScrArea *sa, ScrEdge *onedge);
633 static void splitarea_interactive(ScrArea *area, ScrEdge *onedge);
634
635 static void screen_edge_edit_event(ScrArea *actarea, ScrEdge *actedge, short evt, short val) {
636         if (val) {
637                         // don't allow users to edit full screens
638                 if (actarea && actarea->full) {
639                         return;
640                 }
641         
642                 if (evt==LEFTMOUSE) {
643                         moveareas(actedge);
644                 } else if (evt==MIDDLEMOUSE || evt==RIGHTMOUSE) {
645                         int edgeop;
646                 
647                         if (!actarea->headertype) {
648                                 edgeop= pupmenu("Split Area|Join Areas|Add header");
649                         } else {
650                                 edgeop= pupmenu("Split Area|Join Areas|No header");
651                         }
652
653                         if (edgeop==1) {
654                                 splitarea_interactive(actarea, actedge);
655                         } else if (edgeop==2) {
656                                 joinarea(actarea, actedge);
657                         } else if (edgeop==3) {
658                                 scrarea_change_headertype(actarea, actarea->headertype?0:HEADERDOWN);
659                         }
660                 }
661         }
662 }
663
664 /***/
665
666 void mywindow_init_mainwin(Window *win, int orx, int ory, int sizex, int sizey);
667 void test_scale_screen(bScreen *);
668
669 static void resize_screens(int x, int y, int w, int h) {
670         prefstax= x;
671         prefstay= y;
672         prefsizx= w;
673         prefsizy= h;
674
675         test_scale_screen(G.curscreen);
676         testareas();
677 }
678
679 static void init_mainwin(void)
680 {
681         int orx, ory, sizex, sizey;
682         
683         glEnable(GL_SCISSOR_TEST);
684
685         window_get_position(mainwin, &orx, &ory);
686         window_get_size(mainwin, &sizex, &sizey);
687
688                 /* XXX, temporary stupid fix for minimize at windows */
689         if (!sizex && !sizey) {
690                 return;
691         }
692
693         mywindow_init_mainwin(mainwin, orx, ory, sizex, sizey);
694         resize_screens(orx, ory, sizex, sizey);
695 }
696
697 /***/
698
699 static short afterqueue[MAXQUEUE][3];
700 static int nafterqitems= 0;
701
702 void addafterqueue(short win, unsigned short evt, short val)
703 {
704         if (nafterqitems<MAXQUEUE) {
705                 afterqueue[nafterqitems][0]= win;
706                 afterqueue[nafterqitems][1]= evt;
707                 afterqueue[nafterqitems][2]= val;
708                 nafterqitems++;
709         }
710 }
711
712 static void append_afterqueue(void)
713 {
714         while (nafterqitems) {
715                 short win= afterqueue[nafterqitems-1][0];
716                 unsigned short evt= afterqueue[nafterqitems-1][1];
717                 short val= afterqueue[nafterqitems-1][2];
718
719                 addqueue(win, evt, val);
720                 
721                 nafterqitems--;
722         }
723 }
724
725 static char ext_load_str[256]= {0, 0};
726 void add_readfile_event(char *filename)
727 {       
728         mainqenter(LOAD_FILE, 1);
729         strcpy(ext_load_str, filename);
730         BLI_convertstringcode(ext_load_str, G.sce, G.scene->r.cfra);
731 }
732
733 static short ext_reshape= 0, ext_redraw=0, ext_inputchange=0, ext_mousemove=0;
734
735 static void flush_extqd_events(void) {
736         if (ext_inputchange) {
737                 mainqenter(INPUTCHANGE, ext_inputchange);
738         } else if (ext_reshape) {
739                 mainqenter(RESHAPE, ext_redraw);
740         } else if (ext_redraw) {
741                 mainqenter(REDRAW, ext_redraw);
742         } else if (ext_mousemove) {
743                 short mouse[2];
744                 
745                 getmouseco_sc(mouse);
746                 
747                 mainqenter(MOUSEX, mouse[0]);
748                 mainqenter(MOUSEY, mouse[1]);
749         }
750         
751         ext_inputchange= ext_reshape= ext_redraw= ext_mousemove= 0;
752 }
753
754 unsigned short qtest(void)
755 {
756         if (!mainqtest()) {
757                 winlay_process_events(0);
758         }
759         
760         return mainqtest();
761 }
762
763         /* return true if events are waiting anywhere */
764 int anyqtest(void)
765 {
766         ScrArea *sa;
767
768         if (nafterqitems || qtest()) return 1;
769
770         for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
771                 if (bwin_qtest(sa->win)) return 1;
772                 if (sa->headwin && bwin_qtest(sa->headwin)) return 1;
773         }
774
775         return 0;
776 }
777
778 static void wait_for_event(void)
779 {
780         while (!mainqtest()) {
781                 winlay_process_events(1);
782         }
783 }
784
785 unsigned short screen_qread(short *val, char *ascii)
786 {
787         unsigned short event;
788
789         wait_for_event();
790
791         event= mainqread(val, ascii);
792         
793         if(event==RIGHTSHIFTKEY || event==LEFTSHIFTKEY) {
794                 if(*val) G.qual |= LR_SHIFTKEY;
795                 else G.qual &= ~LR_SHIFTKEY;
796         }
797         else if(event==RIGHTALTKEY || event==LEFTALTKEY) {
798                 if(*val) G.qual |= LR_ALTKEY;
799                 else G.qual &= ~LR_ALTKEY;
800         }
801         else if(event==RIGHTCTRLKEY || event==LEFTCTRLKEY) {
802                 if(*val) G.qual |= LR_CTRLKEY;
803                 else G.qual &= ~LR_CTRLKEY;
804         }
805
806         return event;
807 }
808
809 unsigned short extern_qread_ext(short *val, char *ascii)
810 {
811         /* bewaart de laatste INPUTCHANGE en de laatste REDRAW */
812         unsigned short event;
813         
814         event= screen_qread(val, ascii);
815         if(event==RESHAPE) ext_reshape= *val;
816         else if(event==REDRAW) ext_redraw= *val;
817         else if(event==INPUTCHANGE) ext_inputchange= *val;
818         else if(event==MOUSEY || event==MOUSEX) ext_mousemove= 1;
819         else if((G.qual & LR_CTRLKEY) && event==F3KEY) {
820                 BIF_screendump();
821         }
822
823         return event;
824 }
825 unsigned short extern_qread(short *val)
826 {
827         char ascii;
828         return extern_qread_ext(val, &ascii);
829 }
830
831 void reset_autosave(void) {
832         window_set_timer(mainwin, U.savetime*60*1000, AUTOSAVE_FILE);
833 }
834
835 static void screen_dispatch_events(void) {
836         int events_remaining= 1;
837         ScrArea *sa;
838
839         while (events_remaining) {
840                 events_remaining= 0;
841                                 
842                 winqueue_break= 0;
843                 for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
844                                 /* bewust eerst header afhandelen, dan rest. Header is soms init */
845                         if (sa->headwin && bwin_qtest(sa->headwin)) {
846                                 scrarea_dispatch_header_events(sa);
847                                 events_remaining= 1;
848                         }
849                         if (winqueue_break) break;
850
851                         if (bwin_qtest(sa->win)) {
852                                 scrarea_dispatch_events(sa);
853                                 events_remaining= 1;
854                         }
855                         if (winqueue_break) break;
856                 }
857
858                 if (winqueue_break) break;
859         }
860
861         if (dodrawscreen) {
862                 drawscreen();
863                 dodrawscreen= 0;
864         }
865         
866         screen_swapbuffers();
867 }
868
869 static ScrArea *screen_find_area_for_pt(bScreen *sc, short *mval) 
870 {
871         ScrArea *sa;
872         
873         for (sa= sc->areabase.first; sa; sa= sa->next)
874                 if (BLI_in_rcti(&sa->totrct, mval[0], mval[1]))
875                         return sa;
876         
877         return NULL;
878 }
879
880 void screenmain(void)
881 {
882         int has_input= 1;
883         int firsttime = 1;
884         while (1) {
885                 unsigned short event;
886                 short val, towin;
887                 char ascii;
888
889                 flush_extqd_events();
890                 if (nafterqitems && !qtest()) {
891                         append_afterqueue();
892                         event= 0;
893                 } else {
894                         event= screen_qread(&val, &ascii);
895                 }
896                 
897                 window_make_active(mainwin);
898                 
899                 if (event==INPUTCHANGE) {
900                         has_input= val;
901                 }
902                 
903                 if (has_input) {
904                         ScrArea *newactarea;
905                         int newactwin;
906                         short mval[2];
907
908                         getmouseco_sc(mval);
909                         newactarea= screen_find_area_for_pt(G.curscreen, mval);                 
910
911                         if (newactarea) {
912                                 if (BLI_in_rcti(&newactarea->headrct, mval[0], mval[1])) {
913                                         newactwin= newactarea->headwin;
914                                 } else {
915                                         newactwin= newactarea->win;
916                                 }
917                         } else {
918                                 newactwin= 0;
919                         }
920
921                         if (newactarea && (newactarea != g_activearea)) {
922                                 if (g_activearea) scrarea_queue_headredraw(g_activearea);
923                                 scrarea_queue_headredraw(newactarea);
924                                 set_cursor(newactarea->cursor);
925                                 g_activearea= newactarea;
926                         }
927
928                         G.curscreen->winakt= newactwin;
929                         if (G.curscreen->winakt) {
930                                 areawinset(G.curscreen->winakt);
931                                 set_cursor(choose_cursor(g_activearea));
932                         }
933                 } else {
934                         if (g_activearea) {
935                                 scrarea_queue_headredraw(g_activearea);
936                         }
937                         g_activearea= NULL;
938                         G.curscreen->winakt= 0;
939                 }
940
941                 towin= 0;
942                 if (event==WINCLOSE) {
943                         exit_usiblender();
944                 } 
945                 else if (event==DRAWEDGES) {
946                         dodrawscreen= 1;
947                 }
948                 else if (event==RESHAPE) {
949                         init_mainwin();
950                         markdirty_all();
951                         dodrawscreen= 1;
952                 }
953                 else if (event==REDRAW) {
954                         markdirty_all();
955                         dodrawscreen= 1;
956                 }
957                 else if (event==AUTOSAVE_FILE) {
958                         BIF_write_autosave();
959                 }
960                 else if (event==LOAD_FILE) {
961                         BIF_read_file(ext_load_str);
962                         sound_initialize_sounds();
963                 }
964                 else {
965                         towin= 1;
966                 }
967
968                 if (!g_activearea) {
969                         towin= 0;
970                 }
971                 else if (!G.curscreen->winakt) {
972                         ScrEdge *actedge;
973                         short mval[2];
974
975                         getmouseco_sc(mval);
976                         actedge= screen_find_active_scredge(G.curscreen, mval);
977
978                         if (actedge) {
979                                 if (scredge_is_horizontal(actedge)) {
980                                         set_cursor(CURSOR_Y_MOVE);
981                                 } else {
982                                         set_cursor(CURSOR_X_MOVE);
983                                 }
984
985                                 screen_edge_edit_event(g_activearea, actedge, event, val);
986                         } else {
987                                 set_cursor(CURSOR_STD);
988                         }
989                         
990                         towin= 0;
991                 }
992                 else if (event==QKEY) {
993                         if((G.obedit && G.obedit->type==OB_FONT && g_activearea->spacetype==SPACE_VIEW3D)||g_activearea->spacetype==SPACE_TEXT);
994                         else {
995                                 if(val && okee("QUIT BLENDER")) exit_usiblender();
996                                 towin= 0;
997                         }
998                 }
999                 else if (event==ZKEY) {
1000                         if(val && G.qual==(LR_ALTKEY|LR_SHIFTKEY|LR_CTRLKEY)) {
1001                                 extern void set_debug_swapbuffers_ovveride(bScreen *sc, int mode);
1002
1003                                 int which= pupmenu("Swapbuffers%t|Simple|Debug|DebugSwap|Redraw|Default|KillSwap");
1004                                         
1005                                 switch (which) {
1006                                 case 1: set_debug_swapbuffers_ovveride(G.curscreen, 's'); break;
1007                                 case 2: set_debug_swapbuffers_ovveride(G.curscreen, 'd'); break;
1008                                 case 3: set_debug_swapbuffers_ovveride(G.curscreen, 'f'); break;
1009                                 case 4: set_debug_swapbuffers_ovveride(G.curscreen, 'r'); break;
1010                                 case 5: set_debug_swapbuffers_ovveride(G.curscreen, 0); break;
1011                                 case 6: 
1012                                         if (g_activearea) {
1013                                                 g_activearea->head_swap= 0;
1014                                                 g_activearea->win_swap= 0;
1015                                         }
1016                                         break;
1017                                 }
1018                                 towin= 0;
1019                         }
1020                 }
1021                 else if (event==SPACEKEY) {
1022                         if((G.obedit && G.obedit->type==OB_FONT && g_activearea->spacetype==SPACE_VIEW3D)||g_activearea->spacetype==SPACE_TEXT);
1023                         else {
1024                                 if(val) toolbox();
1025                                 towin= 0;
1026                         }
1027                 }
1028                 else if(ELEM(event, LEFTARROWKEY, RIGHTARROWKEY)) {
1029                         if(val && (G.qual & LR_CTRLKEY)) {
1030                                 bScreen *sc= (event==LEFTARROWKEY)?G.curscreen->id.prev:G.curscreen->id.next;
1031                                 if(is_allowed_to_change_screen(sc)) setscreen(sc);
1032                                 g_activearea= NULL;
1033                                 towin= 0;
1034                         }
1035                 }
1036                 else if(ELEM(event, UPARROWKEY, DOWNARROWKEY)) {
1037                         if(val && (G.qual & LR_CTRLKEY)) {
1038                                 area_fullscreen();
1039                                 g_activearea= NULL;
1040                                 towin= 0;
1041                         }
1042                 }
1043                 
1044                 if (towin && event) {
1045                         if (blenderqread(event, val))
1046                                 addqueue_ext(G.curscreen->winakt, event, val, ascii);
1047                 }
1048
1049                         /* only process subwindow queue's once the
1050                          * main queue has been emptyied.
1051                          */
1052                 event= qtest();
1053                 if (event==0 || event==EXECUTE) {
1054                         screen_dispatch_events();
1055                 }
1056
1057                 /* Bizar hack. The event queue has mutated... */
1058                 if ( (firsttime) && (event == 0) ) {
1059                         if (G.fileflags & G_FILE_AUTOPLAY) {
1060                                 // SET AUTOPLAY in G.flags for
1061                                 // other fileloads
1062
1063                                 G.flags |= G_FLAGS_AUTOPLAY;
1064                                 area_autoplayscreen();
1065
1066                                 // Let The Games Begin
1067                                 // fake a 'p' keypress
1068
1069                                 mainqenter(PKEY, 1);
1070                         } else {
1071                                 extern char datatoc_splash_jpg[];
1072                                 extern int datatoc_splash_jpg_size;
1073
1074                                 if (! ((G.main->versionfile >= G.version)
1075                                        || G.save_over)) {
1076                                         splash((void *)datatoc_splash_jpg,
1077                                                datatoc_splash_jpg_size, NULL);
1078                                 }
1079                         }
1080                         firsttime = 0;
1081                 }
1082         }
1083 }
1084
1085 void mainwindow_raise(void) {
1086         window_raise(mainwin);
1087 }
1088 void mainwindow_make_active(void) {
1089         window_make_active(mainwin);
1090 }
1091 void mainwindow_close(void) {
1092         window_destroy(mainwin);
1093         mainwin= NULL;
1094 }
1095
1096 /* *********  AREAS  ************* */
1097
1098 void setprefsize(int stax, int stay, int sizx, int sizy)
1099 {
1100         int scrwidth, scrheight;
1101         
1102         winlay_get_screensize(&scrwidth, &scrheight);
1103         
1104         if(stax<0) stax= 0;
1105         if(stay<0) stay= 0;
1106         if(sizx<320) sizx= 320;
1107         if(sizy<256) sizy= 256;
1108
1109         if(stax+sizx>scrwidth) sizx= scrwidth-stax;
1110         if(stay+sizy>scrheight) sizy= scrheight-stay;
1111         if(sizx<320 || sizy<256) {
1112                 printf("ERROR: illegal prefsize\n");
1113                 return;
1114         }
1115         
1116         prefstax= stax;
1117         prefstay= stay;
1118         prefsizx= sizx;
1119         prefsizy= sizy;
1120
1121         start_maximized= 0;
1122 }
1123
1124
1125 static ScrVert *screen_addvert(bScreen *sc, short x, short y)
1126 {
1127         ScrVert *sv= MEM_callocN(sizeof(ScrVert), "addscrvert");
1128         sv->vec.x= x;
1129         sv->vec.y= y;
1130         
1131         BLI_addtail(&sc->vertbase, sv);
1132         return sv;
1133 }
1134
1135 static void sortscrvert(ScrVert **v1, ScrVert **v2)
1136 {
1137         ScrVert *tmp;
1138         
1139         if ((long)*v1 > (long)*v2) {
1140                 tmp= *v1;
1141                 *v1= *v2;
1142                 *v2= tmp;       
1143         }
1144 }
1145
1146 static ScrEdge *screen_addedge(bScreen *sc, ScrVert *v1, ScrVert *v2)
1147 {
1148         ScrEdge *se= MEM_callocN(sizeof(ScrEdge), "addscredge");
1149
1150         sortscrvert(&v1, &v2);
1151         se->v1= v1;
1152         se->v2= v2;
1153         
1154         BLI_addtail(&sc->edgebase, se);
1155         return se;
1156 }
1157
1158 static ScrEdge *screen_findedge(bScreen *sc, ScrVert *v1, ScrVert *v2)
1159 {
1160         ScrEdge *se;
1161
1162         sortscrvert(&v1, &v2);
1163         for (se= sc->edgebase.first; se; se= se->next)
1164                 if(se->v1==v1 && se->v2==v2)
1165                         return se;
1166
1167         return NULL;
1168 }
1169
1170 static void removedouble_scrverts(void)
1171 {
1172         ScrVert *v1, *verg;
1173         ScrEdge *se;
1174         ScrArea *sa;
1175         
1176         verg= G.curscreen->vertbase.first;
1177         while(verg) {
1178                 if(verg->newv==0) {     /* !!! */
1179                         v1= verg->next;
1180                         while(v1) {
1181                                 if(v1->newv==0) {       /* !?! */
1182                                         if(v1->vec.x==verg->vec.x && v1->vec.y==verg->vec.y) {
1183                                                 /* printf("doublevert\n"); */
1184                                                 v1->newv= verg;
1185                                         }
1186                                 }
1187                                 v1= v1->next;
1188                         }
1189                 }
1190                 verg= verg->next;
1191         }
1192         
1193         /* vervang pointers in edges en vlakken */
1194         se= G.curscreen->edgebase.first;
1195         while(se) {
1196                 if(se->v1->newv) se->v1= se->v1->newv;
1197                 if(se->v2->newv) se->v2= se->v2->newv;
1198                 /* edges zijn veranderd: dus.... */
1199                 sortscrvert(&(se->v1), &(se->v2));
1200                 se= se->next;
1201         }
1202         sa= G.curscreen->areabase.first;
1203         while(sa) {
1204                 if(sa->v1->newv) sa->v1= sa->v1->newv;
1205                 if(sa->v2->newv) sa->v2= sa->v2->newv;
1206                 if(sa->v3->newv) sa->v3= sa->v3->newv;
1207                 if(sa->v4->newv) sa->v4= sa->v4->newv;
1208                 sa= sa->next;
1209         }
1210         
1211         /* verwijderen */
1212         verg= G.curscreen->vertbase.first;
1213         while(verg) {
1214                 v1= verg->next;
1215                 if(verg->newv) {
1216                         BLI_remlink(&G.curscreen->vertbase, verg);
1217                         MEM_freeN(verg);
1218                 }
1219                 verg= v1;
1220         }
1221         
1222 }
1223
1224 static void removenotused_scrverts(void)
1225 {
1226         ScrVert *sv, *svn;
1227         ScrEdge *se;
1228
1229         /* ga ervan uit dat de edges goed zijn */
1230         
1231         se= G.curscreen->edgebase.first;
1232         while(se) {
1233                 se->v1->flag= 1;
1234                 se->v2->flag= 1;
1235                 se= se->next;
1236         }
1237         
1238         sv= G.curscreen->vertbase.first;
1239         while(sv) {
1240                 svn= sv->next;
1241                 if(sv->flag==0) {
1242                         BLI_remlink(&G.curscreen->vertbase, sv);
1243                         MEM_freeN(sv);
1244                 }
1245                 else sv->flag= 0;
1246                 sv= svn;
1247         }
1248 }
1249
1250 static void removedouble_scredges(void)
1251 {
1252         ScrEdge *verg, *se, *sn;
1253         
1254         /* vergelijken */
1255         verg= G.curscreen->edgebase.first;
1256         while(verg) {
1257                 se= verg->next;
1258                 while(se) {
1259                         sn= se->next;
1260                         if(verg->v1==se->v1 && verg->v2==se->v2) {
1261                                 BLI_remlink(&G.curscreen->edgebase, se);
1262                                 MEM_freeN(se);
1263                         }
1264                         se= sn;
1265                 }
1266                 verg= verg->next;
1267         }
1268 }
1269
1270 static void removenotused_scredges(void)
1271 {
1272         ScrEdge *se, *sen;
1273         ScrArea *sa;
1274         int a=0;
1275         
1276         /* zet flag als edge gebruikt wordt in area */
1277         sa= G.curscreen->areabase.first;
1278         while(sa) {
1279                 se= screen_findedge(G.curscreen, sa->v1, sa->v2);
1280                 if(se==0) printf("error: area %d edge 1 bestaat niet\n", a);
1281                 else se->flag= 1;
1282                 se= screen_findedge(G.curscreen, sa->v2, sa->v3);
1283                 if(se==0) printf("error: area %d edge 2 bestaat niet\n", a);
1284                 else se->flag= 1;
1285                 se= screen_findedge(G.curscreen, sa->v3, sa->v4);
1286                 if(se==0) printf("error: area %d edge 3 bestaat niet\n", a);
1287                 else se->flag= 1;
1288                 se= screen_findedge(G.curscreen, sa->v4, sa->v1);
1289                 if(se==0) printf("error: area %d edge 4 bestaat niet\n", a);
1290                 else se->flag= 1;
1291                 sa= sa->next;
1292                 a++;
1293         }
1294         se= G.curscreen->edgebase.first;
1295         while(se) {
1296                 sen= se->next;
1297                 if(se->flag==0) {
1298                         BLI_remlink(&G.curscreen->edgebase, se);
1299                         MEM_freeN(se);
1300                 }
1301                 else se->flag= 0;
1302                 se= sen;
1303         }
1304 }
1305
1306 void calc_arearcts(ScrArea *sa)
1307 {
1308
1309         if(sa->v1->vec.x>0) sa->totrct.xmin= sa->v1->vec.x+EDGEWIDTH2+1;
1310         else sa->totrct.xmin= sa->v1->vec.x;
1311         if(sa->v4->vec.x<G.curscreen->sizex-1) sa->totrct.xmax= sa->v4->vec.x-EDGEWIDTH2-1;
1312         else sa->totrct.xmax= sa->v4->vec.x;
1313         
1314         if(sa->v1->vec.y>0) sa->totrct.ymin= sa->v1->vec.y+EDGEWIDTH2+1;
1315         else sa->totrct.ymin= sa->v1->vec.y;
1316         if(sa->v2->vec.y<G.curscreen->sizey-1) sa->totrct.ymax= sa->v2->vec.y-EDGEWIDTH2-1;
1317         else sa->totrct.ymax= sa->v2->vec.y;
1318         
1319         sa->winrct= sa->totrct;
1320         if(sa->headertype) {
1321                 sa->headrct= sa->totrct;
1322                 if(sa->headertype==HEADERDOWN) {
1323                         sa->headrct.ymax= sa->headrct.ymin+HEADERY-1;
1324                         sa->winrct.ymin= sa->headrct.ymax+1;
1325                 }
1326                 else if(sa->headertype==HEADERTOP) {
1327                         sa->headrct.ymin= sa->headrct.ymax-HEADERY+1;
1328                         sa->winrct.ymax= sa->headrct.ymin-1;
1329                 }
1330         }
1331         if(sa->winrct.ymin>sa->winrct.ymax) sa->winrct.ymin= sa->winrct.ymax;
1332         
1333         /* als speedup voor berekeningen */
1334         sa->winx= sa->winrct.xmax-sa->winrct.xmin+1;
1335         sa->winy= sa->winrct.ymax-sa->winrct.ymin+1;
1336 }
1337
1338 static void openheadwin(ScrArea *sa)
1339 {
1340         sa->headwin= myswinopen(G.curscreen->mainwin,
1341                 sa->headrct.xmin, sa->headrct.xmax, sa->headrct.ymin, sa->headrct.ymax);
1342
1343         glMatrixMode(GL_MODELVIEW);
1344         
1345         areawinar[sa->headwin]= sa;     /* anders doet addqueue het niet */
1346         addqueue(sa->headwin, CHANGED, 1);
1347 }
1348
1349 static void openareawin(ScrArea *sa)
1350 {
1351         sa->win= myswinopen(G.curscreen->mainwin, 
1352                 sa->winrct.xmin, sa->winrct.xmax, sa->winrct.ymin, sa->winrct.ymax);
1353
1354         areawinar[sa->win]= sa; /* anders doet addqueue het niet */
1355         addqueue(sa->win, CHANGED, 1);
1356 }
1357
1358 static void closeheadwin(ScrArea *sa)
1359 {
1360         if(sa->headwin) mywinclose(sa->headwin);
1361         sa->headwin= 0;
1362 }
1363
1364 static void closeareawin(ScrArea *sa)
1365 {
1366         uiFreeBlocksWin(&sa->uiblocks, sa->win);
1367
1368         if(sa->win) mywinclose(sa->win);
1369         sa->win= 0;
1370 }
1371
1372 static void del_area(ScrArea *sa)
1373 {
1374         closeareawin(sa);
1375         closeheadwin(sa);
1376
1377         freespacelist(&sa->spacedata);
1378         
1379         uiFreeBlocks(&sa->uiblocks);
1380         
1381         if(sa==curarea) curarea= 0;
1382         if(sa==g_activearea) g_activearea= 0;
1383 }
1384
1385 static void copy_areadata(ScrArea *sa1, ScrArea *sa2)
1386 {
1387         sa1->headertype= sa2->headertype;
1388         sa1->spacetype= sa2->spacetype;
1389         Mat4CpyMat4(sa1->winmat, sa2->winmat);
1390         
1391         freespacelist(&sa1->spacedata);
1392         
1393         duplicatespacelist(sa1, &sa1->spacedata, &sa2->spacedata);
1394 }
1395
1396 static ScrArea *screen_addarea(bScreen *sc, ScrVert *v1, ScrVert *v2, ScrVert *v3, ScrVert *v4, short headertype, short spacetype)
1397 {
1398         ScrArea *sa= MEM_callocN(sizeof(ScrArea), "addscrarea");
1399         sa->cursor= CURSOR_STD;
1400         sa->v1= v1;
1401         sa->v2= v2;
1402         sa->v3= v3;
1403         sa->v4= v4;
1404         sa->headertype= headertype;
1405         sa->spacetype= spacetype;
1406
1407         calc_arearcts(sa);
1408
1409         if (sa->headertype) openheadwin(sa);
1410         openareawin(sa);
1411
1412         BLI_addtail(&sc->areabase, sa);
1413         return sa;
1414 }
1415
1416 static int rcti_eq(rcti *a, rcti *b) {
1417         return ((a->xmin==b->xmin && a->xmax==b->xmax) &&
1418                         (a->ymin==b->ymin && a->ymax==b->ymax));
1419 }
1420
1421 static void testareas(void)
1422 {
1423         ScrArea *sa;
1424
1425         /* testen of header er moet zijn, of weg moet, of verplaatst */
1426         /* testen of window er moet zijn, of weg moet, of verplaatst */
1427
1428         for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
1429                 rcti oldhr= sa->headrct;
1430                 rcti oldwr= sa->winrct;
1431                 
1432                 calc_arearcts(sa);
1433
1434                         /* test header */
1435                 if (sa->headwin) {
1436                         if (!rcti_eq(&oldhr, &sa->headrct)) {
1437                                 mywinposition(sa->headwin, sa->headrct.xmin, sa->headrct.xmax, sa->headrct.ymin, sa->headrct.ymax);
1438                                 addqueue(sa->headwin, CHANGED, 1);
1439                         }
1440                                 
1441                         if(sa->headbutlen<sa->winx) {
1442                                 sa->headbutofs= 0;
1443                                 addqueue(sa->headwin, CHANGED, 1);
1444                         }
1445                         else if(sa->headbutofs+sa->winx > sa->headbutlen) {
1446                                 sa->headbutofs= sa->headbutlen-sa->winx;
1447                                 addqueue(sa->headwin, CHANGED, 1);
1448                         }
1449                 }
1450
1451                 if (!rcti_eq(&oldwr, &sa->winrct)) {
1452                         mywinposition(sa->win, sa->winrct.xmin, sa->winrct.xmax, sa->winrct.ymin, sa->winrct.ymax);
1453                         addqueue(sa->win, CHANGED, 1);
1454                 }
1455         }
1456         
1457                 /* remake global windowarray */
1458         memset(areawinar, 0, sizeof(void *)*MAXWIN);
1459         for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
1460                 areawinar[sa->headwin]= sa;
1461                 areawinar[sa->win]= sa;
1462         }
1463         
1464                 /* test of winakt in orde is */ 
1465         if( areawinar[G.curscreen->winakt]==0) G.curscreen->winakt= 0;
1466 }
1467
1468 static ScrArea *test_edge_area(ScrArea *sa, ScrEdge *se)
1469 {
1470         /* test of edge in area ligt, zo niet, 
1471            vind een area die 'm wel heeft */
1472   
1473         ScrEdge *se1=0, *se2=0, *se3=0, *se4=0;
1474         
1475         if(sa) {
1476                 se1= screen_findedge(G.curscreen, sa->v1, sa->v2);
1477                 se2= screen_findedge(G.curscreen, sa->v2, sa->v3);
1478                 se3= screen_findedge(G.curscreen, sa->v3, sa->v4);
1479                 se4= screen_findedge(G.curscreen, sa->v4, sa->v1);
1480         }
1481         if(se1!=se && se2!=se && se3!=se && se4!=se) {
1482                 
1483                 sa= G.curscreen->areabase.first;
1484                 while(sa) {
1485                         /* een beetje optimaliseren? */
1486                         if(se->v1==sa->v1 || se->v1==sa->v2 || se->v1==sa->v3 || se->v1==sa->v4) {
1487                                 se1= screen_findedge(G.curscreen, sa->v1, sa->v2);
1488                                 se2= screen_findedge(G.curscreen, sa->v2, sa->v3);
1489                                 se3= screen_findedge(G.curscreen, sa->v3, sa->v4);
1490                                 se4= screen_findedge(G.curscreen, sa->v4, sa->v1);
1491                                 if(se1==se || se2==se || se3==se || se4==se) return sa;
1492                         }
1493                         sa= sa->next;
1494                 }
1495         }
1496
1497         return sa;      /* is keurig 0 als niet gevonden */
1498 }
1499
1500 ScrArea *closest_bigger_area(void)
1501 {
1502         ScrArea *sa, *big=0;
1503         float cent[3], vec[3],len, len1, len2, len3, dist=1000;
1504         short mval[2];
1505         
1506         getmouseco_sc(mval);
1507         
1508         cent[0]= mval[0];
1509         cent[1]= mval[1];
1510         cent[2]= vec[2]= 0;
1511
1512         sa= G.curscreen->areabase.first;
1513         while(sa) {
1514                 if(sa!=curarea) {
1515                         if(sa->winy>=curarea->winy) {
1516                         
1517                                 /* mimimum van vier hoekpunten */
1518                                 vec[0]= sa->v1->vec.x; vec[1]= sa->v1->vec.y;
1519                                 len= VecLenf(vec, cent);
1520                                 vec[0]= sa->v2->vec.x; vec[1]= sa->v2->vec.y;
1521                                 len1= VecLenf(vec, cent);
1522                                 vec[0]= sa->v3->vec.x; vec[1]= sa->v3->vec.y;
1523                                 len2= VecLenf(vec, cent);
1524                                 vec[0]= sa->v4->vec.x; vec[1]= sa->v4->vec.y;
1525                                 len3= VecLenf(vec, cent);
1526                                 
1527                                 len= MIN4(len, len1, len2, len3);
1528                                 
1529                                 /* plus centrum */
1530                                 vec[0]= (sa->v2->vec.x+sa->v3->vec.x)/2;
1531                                 vec[1]= (sa->v1->vec.y+sa->v2->vec.y)/2;
1532
1533                                 len+= 0.5*VecLenf(vec, cent);
1534                                 
1535                                 /* min afmeting */
1536                                 len-= sa->winy+sa->winx;
1537                                 
1538                                 if(len<dist) {
1539                                         dist= len;
1540                                         big= sa;
1541                                 }
1542                         }
1543                 }
1544                 sa= sa->next;
1545         }
1546         
1547         if(big) return big;
1548         else return curarea;
1549 }
1550
1551 /* ************ SCREENBEHEER ************** */
1552
1553 static int statechanged= 0;
1554 void BIF_wait_for_statechange(void)
1555 {
1556         if (!statechanged) {
1557                         /* Safety, don't wait more than 0.1 seconds */
1558                 double stime= PIL_check_seconds_timer();
1559                 while (!statechanged) {
1560                         winlay_process_events(1);
1561                         if ((PIL_check_seconds_timer()-stime)>0.1) break;
1562                 }
1563                 statechanged= 0;
1564         }
1565 }
1566 void getmouse(short *mval)
1567 {
1568         winlay_process_events(0);
1569         window_get_mouse(mainwin, mval);
1570 }
1571 short get_qual(void)
1572 {
1573         winlay_process_events(0);
1574         return window_get_qual(mainwin);
1575 }
1576 short get_mbut(void)
1577 {
1578         winlay_process_events(0);
1579         return window_get_mbut(mainwin);
1580 }
1581
1582 static unsigned short convert_for_nonumpad(unsigned short event)
1583 {
1584         if (event>=ZEROKEY && event<=NINEKEY) {
1585                 return event - ZEROKEY + PAD0;
1586         } else if (event==MINUSKEY) {
1587                 return PADMINUS;
1588         } else if (event==EQUALKEY) {
1589                 return PADPLUSKEY;
1590         } else if (event==BACKSLASHKEY) {
1591                 return PADSLASHKEY;
1592         } else {
1593                 return event;
1594         }
1595 }
1596
1597 void add_to_mainqueue(Window *win, void *user_data, short evt, short val, char ascii)
1598 {
1599         short qual= window_get_qual(win);
1600
1601         statechanged= 1;
1602
1603         if (U.flag&NONUMPAD) {
1604                 evt= convert_for_nonumpad(evt);
1605         }
1606         
1607                 /* enforce some guarentees about ascii values... these should
1608                  * be enforced in ghost probably - zr
1609                  */
1610
1611         if (!val || !isprint(ascii) || (qual&~LR_SHIFTKEY)) {
1612                 ascii= '\0';
1613         }
1614
1615         mainqenter_ext(evt, val, ascii);
1616 }
1617
1618 static bScreen *addscreen(char *name)           /* gebruik de setprefsize() als je anders dan fullscreen wilt */
1619 {
1620         /* deze functie zet de variabele G.curscreen
1621          * omdat alle hulpfuncties moeten weten welk screen
1622          */
1623         bScreen *sc;
1624         ScrVert *sv1, *sv2, *sv3, *sv4;
1625         short startx, starty, endx, endy;       
1626         
1627         sc= G.curscreen= alloc_libblock(&G.main->screen, ID_SCR, name);
1628
1629         if (!prefsizx) {
1630                 prefstax= 0;
1631                 prefstay= 0;
1632                 
1633                 winlay_get_screensize(&prefsizx, &prefsizy);
1634         }
1635
1636         startx= prefstax;
1637         starty= prefstay;
1638         endx= prefstax+prefsizx-1;
1639         endy= prefstay+prefsizy-1;
1640
1641         sc->startx= startx;     sc->starty= starty;
1642         sc->endx= endx; sc->endy= endy;
1643         sc->sizex= sc->endx-sc->startx+1;
1644         sc->sizey= sc->endy-sc->starty+1;
1645         
1646         sc->scene= G.scene;
1647         
1648         if (!mainwin) {
1649                 mainwin= window_open("Blender", sc->startx, sc->starty, sc->sizex, sc->sizey, start_maximized);
1650                 if (!mainwin) {
1651                         printf("ERROR: Unable to open Blender window\n");
1652                         exit(1);
1653                 }
1654                 
1655                 window_set_handler(mainwin, add_to_mainqueue, NULL);
1656                 init_mainwin();
1657                 mywinset(1);
1658         
1659                 glMatrixMode(GL_PROJECTION);
1660                 glLoadIdentity();
1661                 myortho2(-0.5, sc->sizex-0.5, -0.5, sc->sizey-0.5);
1662                 glMatrixMode(GL_MODELVIEW);
1663                 glLoadIdentity();
1664
1665                 glDrawBuffer(GL_FRONT);
1666                 glClearColor(.45, .45, .45, 0.0);
1667                 glClear(GL_COLOR_BUFFER_BIT);
1668                 glDrawBuffer(GL_BACK);
1669                 
1670                 warp_pointer(sc->sizex/2,  sc->sizey/2);
1671                 
1672                 mainqenter(REDRAW, 1);
1673         }
1674
1675         sc->mainwin= 1;
1676         
1677         sv1= screen_addvert(sc, 0, 0);
1678         sv2= screen_addvert(sc, 0, sc->endy-sc->starty);
1679         sv3= screen_addvert(sc, sc->sizex-1, sc->sizey-1);
1680         sv4= screen_addvert(sc, sc->sizex-1, 0);
1681         
1682         screen_addedge(sc, sv1, sv2);
1683         screen_addedge(sc, sv2, sv3);
1684         screen_addedge(sc, sv3, sv4);
1685         screen_addedge(sc, sv4, sv1);
1686
1687         screen_addarea(sc, sv1, sv2, sv3, sv4, HEADERDOWN, SPACE_INFO);
1688         
1689         G.curscreen= sc;
1690
1691         return sc;
1692 }
1693
1694 void setscreen(bScreen *sc)
1695 {
1696         bScreen *sc1;
1697         ScrArea *sa;
1698         short mval[2];
1699         
1700         if(sc->full) {                          /* vind de bijhorende full */
1701                 sc1= G.main->screen.first;
1702                 while(sc1) {
1703                         sa= sc1->areabase.first;
1704                         if(sa->full==sc) {
1705                                 sc= sc1;
1706                                 break;
1707                         }
1708                         sc1= sc1->id.next;
1709                 }
1710                 if(sc1==0) printf("setscreen error\n");
1711         }
1712
1713         /* G.curscreen de-activeren */
1714         if (G.curscreen && G.curscreen != sc) {
1715                 sa= G.curscreen->areabase.first;
1716                 while(sa) {
1717                         if(sa->win) mywinclose(sa->win);
1718                         sa->win= 0;
1719                         if(sa->headwin) mywinclose(sa->headwin);
1720                         sa->headwin= 0;
1721                         
1722                         uiFreeBlocks(&sa->uiblocks);
1723                         
1724                         sa= sa->next;
1725                 }               
1726         }
1727
1728         if (G.curscreen != sc) {
1729                 mywinset(sc->mainwin);
1730         }
1731         
1732         G.curscreen= sc;
1733
1734         for (sa= sc->areabase.first; sa; sa= sa->next) {
1735                         /* XXX, fixme zr */
1736 /*              if (sa->win || sa->headwin) */
1737 /*                      printf("error in setscreen (win): %d, %d\n", sa->win, sa->headwin); */
1738                 if (!sa->win)
1739                         openareawin(sa);
1740                 if (!sa->headwin && sa->headertype)
1741                         openheadwin(sa);
1742         }
1743
1744         /* recalculate winakt */
1745         getmouseco_sc(mval);
1746
1747         test_scale_screen(sc);
1748         testareas();
1749         
1750         for (sa= sc->areabase.first; sa; sa= sa->next) {
1751                 SpaceLink *sl;
1752
1753                 for (sl= sa->spacedata.first; sl; sl= sl->next) {
1754                         sl->area= sa;
1755
1756                         if (sl->spacetype==SPACE_OOPS) {
1757                                 SpaceOops *soops= (SpaceOops*) sl;
1758
1759                                 /* patch als deze in oude files zit */
1760                                 if (soops->v2d.cur.xmin==soops->v2d.cur.xmax) {
1761                                         extern void init_v2d_oops(View2D*);
1762                                         init_v2d_oops(&soops->v2d);
1763                                 }
1764                         }
1765                 }
1766                 
1767                 sa->cursor= CURSOR_STD;
1768         }
1769
1770         G.scene= sc->scene;
1771         countall();
1772         
1773         G.curscreen->winakt= 0;
1774         curarea= sc->areabase.first;
1775         
1776         mainqenter(DRAWEDGES, 1);
1777         dodrawscreen= 1;                /* patch! even gets lost,,,? */
1778
1779         winqueue_break= 1;              /* overal uit de queue's gaan */
1780 }
1781
1782 static void splitarea(ScrArea *sa, char dir, float fac);
1783
1784 void area_fullscreen(void)      /* met curarea */
1785 {
1786         /* deze funktie toggelt: als area full is wordt de parent weer zichtbaar */
1787         bScreen *sc, *oldscreen;
1788         ScrArea *newa, *old;
1789         short headertype, fulltype;
1790         
1791         if(curarea->full) {
1792                 sc= curarea->full;      /* de oude screen */
1793                 fulltype = sc->full;
1794
1795                 // refuse to go out of SCREENAUTOPLAY as long as G_FLAGS_AUTOPLAY
1796                 // is set
1797
1798                 if (fulltype != SCREENAUTOPLAY || (G.flags & G_FLAGS_AUTOPLAY) == 0) {
1799                         sc->full= 0;
1800                 
1801                         /* vind oude area */
1802                         old= sc->areabase.first;
1803                         while(old) {
1804                                 if(old->full) break;
1805                                 old= old->next;
1806                         }
1807                         if(old==0) {error("something wrong in areafullscreen"); return;}
1808                 
1809                         if (fulltype == SCREENAUTOPLAY) {
1810                                 // in autoplay screens the headers are disabled by 
1811                                 // default. So use the old headertype instead
1812                                 headertype = old->headertype;
1813                         } else {
1814                                 // normal fullscreen. Use current headertype
1815                                 headertype = curarea->headertype;
1816                         }
1817
1818                         copy_areadata(old, curarea);
1819                         old->headertype = headertype;
1820
1821                         old->full= 0;
1822                 
1823                         unlink_screen(G.curscreen);
1824                         free_libblock(&G.main->screen, G.curscreen);
1825                         G.curscreen= NULL;
1826
1827                         setscreen(sc);
1828                 }
1829                 
1830         }
1831         else {
1832                 /* is er maar 1 area? */
1833                 if(G.curscreen->areabase.first==G.curscreen->areabase.last) return;
1834                 if(curarea->spacetype==SPACE_INFO) return;
1835                 
1836                 G.curscreen->full = SCREENFULL;
1837                 
1838                 old= curarea;           
1839                 oldscreen= G.curscreen;
1840                 sc= addscreen("temp");          /* deze zet G.curscreen */
1841
1842                 splitarea( (ScrArea *)sc->areabase.first, 'h', 0.99);
1843                 newa= sc->areabase.first;
1844                 newspace(newa->next, SPACE_INFO);
1845                 
1846                 curarea= old;
1847                 G.curscreen= oldscreen; /* moet voor setscreen */
1848                 
1849                 /* area kopieeren */
1850                 copy_areadata(newa, curarea);
1851                 
1852                 curarea->full= oldscreen;
1853                 newa->full= oldscreen;
1854                 newa->next->full= oldscreen;
1855                 
1856                 setscreen(sc);
1857                 wich_cursor(newa);
1858         }
1859 }
1860
1861 static void area_autoplayscreen(void)
1862 {
1863         bScreen *sc, *oldscreen;
1864         ScrArea *newa, *old, *sa;
1865         
1866         if (curarea->full) {
1867                 area_fullscreen();
1868         }
1869
1870         if (curarea->full == NULL) { 
1871                 sa = G.curscreen->areabase.first;
1872                 while (sa) {
1873                         if (sa->spacetype == SPACE_VIEW3D) {
1874                                 break;
1875                         }
1876                         sa= sa->next;
1877                 }
1878
1879                 if (sa) {
1880                         areawinset(sa->win);
1881                         G.curscreen->full = SCREENAUTOPLAY;
1882                         
1883                         old= curarea;           
1884                         oldscreen= G.curscreen;
1885                         sc= addscreen("temp");          /* deze zet G.curscreen */
1886         
1887                         newa= sc->areabase.first;
1888                         
1889                         curarea= old;
1890                         G.curscreen= oldscreen; /* moet voor setscreen */
1891                         
1892                         /* copy area settings */
1893                         copy_areadata(newa, curarea);
1894                         newa->headertype= 0;
1895                         
1896                         curarea->full= oldscreen;
1897                         newa->full= oldscreen;
1898         
1899                         setscreen(sc);
1900                         wich_cursor(newa);
1901                 }
1902         }
1903 }
1904
1905 static void copy_screen(bScreen *to, bScreen *from)
1906 {
1907         ScrVert *s1, *s2;
1908         ScrEdge *se;
1909         ScrArea *sa;
1910         ListBase lbase;
1911         
1912         /* alles van to vrijgeven */
1913         free_screen(to);
1914         winqueue_break= 1;      /* overal uit queue's gaan */
1915         
1916         duplicatelist(&to->vertbase, &from->vertbase);
1917         duplicatelist(&to->edgebase, &from->edgebase);
1918         duplicatelist(&to->areabase, &from->areabase);
1919         
1920         s1= from->vertbase.first;
1921         s2= to->vertbase.first;
1922         while(s1) {
1923                 s1->newv= s2;
1924                 s2= s2->next;
1925                 s1= s1->next;
1926         }
1927         se= to->edgebase.first;
1928         while(se) {
1929                 se->v1= se->v1->newv;
1930                 se->v2= se->v2->newv;
1931                 sortscrvert(&(se->v1), &(se->v2));
1932                 se= se->next;
1933         }
1934
1935         sa= to->areabase.first;
1936         while(sa) {
1937                 sa->v1= sa->v1->newv;
1938                 sa->v2= sa->v2->newv;
1939                 sa->v3= sa->v3->newv;
1940                 sa->v4= sa->v4->newv;
1941                 sa->win= 0;
1942                 sa->headwin= 0;
1943                 
1944                 sa->uiblocks.first= sa->uiblocks.last= NULL;
1945                 
1946                 duplicatespacelist(sa, &lbase, &sa->spacedata);
1947                 sa->spacedata= lbase;
1948                 
1949                 sa= sa->next;
1950         }
1951         
1952         /* op nul zetten (nodig?) */
1953         s1= from->vertbase.first;
1954         while(s1) {
1955                 s1->newv= 0;
1956                 s1= s1->next;
1957         }
1958 }
1959
1960 void duplicate_screen(void)
1961 {
1962         bScreen *sc, *oldscreen;
1963         
1964         if(G.curscreen->full != SCREENNORMAL) return;
1965         
1966         /* nieuw screen maken: */
1967
1968         oldscreen= G.curscreen;
1969         sc= addscreen(oldscreen->id.name+2);    /* deze zet G.curscreen */
1970         copy_screen(sc, oldscreen);
1971
1972         G.curscreen= oldscreen;
1973         setscreen(sc);
1974
1975 }
1976
1977
1978 /* ************ END SCREENBEHEER ************** */
1979 /* ************  JOIN/SPLIT/MOVE ************** */
1980
1981 static void joinarea(ScrArea *sa, ScrEdge *onedge)
1982 {
1983         ScrArea *sa2;
1984         ScrArea *up=0, *down=0, *right=0, *left=0;
1985         ScrEdge *setest;
1986         short val=0;
1987         
1988         sa= test_edge_area(sa, onedge);
1989         if (sa==0) return;
1990
1991         /* welke edges kunnen ermee? */
1992         /* vind richtingen met zelfde edge */
1993         sa2= G.curscreen->areabase.first;
1994         while(sa2) {
1995                 if(sa2 != sa) {
1996                         setest= screen_findedge(G.curscreen, sa2->v1, sa2->v2);
1997                         if(onedge==setest) right= sa2;
1998                         setest= screen_findedge(G.curscreen, sa2->v2, sa2->v3);
1999                         if(onedge==setest) down= sa2;
2000                         setest= screen_findedge(G.curscreen, sa2->v3, sa2->v4);
2001                         if(onedge==setest) left= sa2;
2002                         setest= screen_findedge(G.curscreen, sa2->v4, sa2->v1);
2003                         if(onedge==setest) up= sa2;
2004                 }
2005                 sa2= sa2->next;
2006         }
2007         
2008         sa2= 0;
2009         setest= 0;
2010         
2011         if(left) val++;
2012         if(up) val++;
2013         if(right) val++;
2014         if(down) val++;
2015         
2016         if(val==0) return;
2017         else if(val==1) {
2018                 if(left) sa2= left;
2019                 else if(up) sa2= up;
2020                 else if(right) sa2= right;
2021                 else if(down) sa2= down;
2022         }
2023         
2024         
2025         if(sa2) {
2026                 /* nieuwe area is oude sa */
2027                 if(sa2==left) {
2028                         sa->v1= sa2->v1;
2029                         sa->v2= sa2->v2;
2030                         screen_addedge(G.curscreen, sa->v2, sa->v3);
2031                         screen_addedge(G.curscreen, sa->v1, sa->v4);
2032                 }
2033                 else if(sa2==up) {
2034                         sa->v2= sa2->v2;
2035                         sa->v3= sa2->v3;
2036                         screen_addedge(G.curscreen, sa->v1, sa->v2);
2037                         screen_addedge(G.curscreen, sa->v3, sa->v4);
2038                 }
2039                 else if(sa2==right) {
2040                         sa->v3= sa2->v3;
2041                         sa->v4= sa2->v4;
2042                         screen_addedge(G.curscreen, sa->v2, sa->v3);
2043                         screen_addedge(G.curscreen, sa->v1, sa->v4);
2044                 }
2045                 else if(sa2==down) {
2046                         sa->v1= sa2->v1;
2047                         sa->v4= sa2->v4;
2048                         screen_addedge(G.curscreen, sa->v1, sa->v2);
2049                         screen_addedge(G.curscreen, sa->v3, sa->v4);
2050                 }
2051         
2052                 /* edge en area weg */
2053                 /* remlink(&G.curscreen->edgebase, setest); */
2054                 /* freeN(setest); */
2055                 del_area(sa2);
2056                 BLI_remlink(&G.curscreen->areabase, sa2);
2057                 MEM_freeN(sa2);
2058                 
2059                 removedouble_scredges();
2060                 removenotused_scredges();
2061                 removenotused_scrverts();       /* moet als laatste */
2062                 
2063                 testareas();
2064                 mainqenter(DRAWEDGES, 1);
2065                         /* test cursor en inputwindow */
2066                 mainqenter(MOUSEY, -1);         
2067         }
2068 }
2069
2070 static short testsplitpoint(ScrArea *sa, char dir, float fac)
2071 /* return 0: geen split mogelijk */
2072 /* else return (integer) screencoordinaat splitpunt */
2073 {
2074         short x, y;
2075         
2076         /* area groot genoeg? */
2077         if(sa->v4->vec.x- sa->v1->vec.x <= 2*AREAMINX) return 0;
2078         if(sa->v2->vec.y- sa->v1->vec.y <= 2*AREAMINY) return 0;
2079
2080         /* voor zekerheid */
2081         if(fac<0.0) fac= 0.0;
2082         if(fac>1.0) fac= 1.0;
2083         
2084         if(dir=='h') {
2085                 y= sa->v1->vec.y+ fac*(sa->v2->vec.y- sa->v1->vec.y);
2086                 
2087                 if(sa->v2->vec.y==G.curscreen->sizey-1 && sa->v2->vec.y- y < HEADERY+EDGEWIDTH2) 
2088                         y= sa->v2->vec.y- HEADERY-EDGEWIDTH2;
2089
2090                 else if(sa->v1->vec.y==0 && y- sa->v1->vec.y < HEADERY+EDGEWIDTH2)
2091                         y= sa->v1->vec.y+ HEADERY+EDGEWIDTH2;
2092
2093                 else if(y- sa->v1->vec.y < AREAMINY) y= sa->v1->vec.y+ AREAMINY;
2094                 else if(sa->v2->vec.y- y < AREAMINY) y= sa->v2->vec.y- AREAMINY;
2095                 else y-= (y % AREAGRID);
2096
2097                 return y;
2098         }
2099         else {
2100                 x= sa->v1->vec.x+ fac*(sa->v4->vec.x- sa->v1->vec.x);
2101                 if(x- sa->v1->vec.x < AREAMINX) x= sa->v1->vec.x+ AREAMINX;
2102                 else if(sa->v4->vec.x- x < AREAMINX) x= sa->v4->vec.x- AREAMINX;
2103                 else x-= (x % AREAGRID);
2104
2105                 return x;
2106         }
2107 }
2108
2109 static void splitarea(ScrArea *sa, char dir, float fac)
2110 {
2111         bScreen *sc;
2112         ScrArea *newa;
2113         ScrVert *sv1, *sv2;
2114         short split;
2115         
2116         if(sa==0) return;
2117         
2118         split= testsplitpoint(sa, dir, fac);
2119         if(split==0) return;
2120         
2121         sc= G.curscreen;
2122         
2123         areawinset(sa->win);
2124         
2125         if(dir=='h') {
2126                 /* nieuwe vertices */
2127                 sv1= screen_addvert(sc, sa->v1->vec.x, split);
2128                 sv2= screen_addvert(sc, sa->v4->vec.x, split);
2129                 
2130                 /* nieuwe edges */
2131                 screen_addedge(sc, sa->v1, sv1);
2132                 screen_addedge(sc, sv1, sa->v2);
2133                 screen_addedge(sc, sa->v3, sv2);
2134                 screen_addedge(sc, sv2, sa->v4);
2135                 screen_addedge(sc, sv1, sv2);
2136                 
2137                 /* nieuwe areas: boven */
2138                 newa= screen_addarea(sc, sv1, sa->v2, sa->v3, sv2, sa->headertype, sa->spacetype);
2139                 copy_areadata(newa, sa);
2140
2141                 /* area onder */
2142                 sa->v2= sv1;
2143                 sa->v3= sv2;
2144                 
2145         }
2146         else {
2147                 /* nieuwe vertices */
2148                 sv1= screen_addvert(sc, split, sa->v1->vec.y);
2149                 sv2= screen_addvert(sc, split, sa->v2->vec.y);
2150                 
2151                 /* nieuwe edges */
2152                 screen_addedge(sc, sa->v1, sv1);
2153                 screen_addedge(sc, sv1, sa->v4);
2154                 screen_addedge(sc, sa->v2, sv2);
2155                 screen_addedge(sc, sv2, sa->v3);
2156                 screen_addedge(sc, sv1, sv2);
2157                 
2158                 /* nieuwe areas: links */
2159                 newa= screen_addarea(sc, sa->v1, sa->v2, sv2, sv1, sa->headertype, sa->spacetype);
2160                 copy_areadata(newa, sa);
2161
2162                 /* area rechts */
2163                 sa->v1= sv1;            
2164                 sa->v2= sv2;
2165         }
2166         
2167         /* dubbele vertices en edges verwijderen */
2168         removedouble_scrverts();
2169         removedouble_scredges();
2170         removenotused_scredges();
2171         
2172         mainqenter(DRAWEDGES, 1);
2173         dodrawscreen= 1;                /* patch! even gets lost,,,? */
2174         testareas();
2175 }
2176
2177 static void scrarea_draw_splitpoint(ScrArea *sa, char dir, float fac)
2178 {
2179         int split= testsplitpoint(sa, dir, fac);
2180
2181         if (split) {
2182                 if(dir=='h') {
2183                         glutil_draw_front_xor_line(sa->totrct.xmin, split, sa->totrct.xmax, split);
2184                         glutil_draw_front_xor_line(sa->totrct.xmin, split-1, sa->totrct.xmax, split-1);
2185                 } else {
2186                         glutil_draw_front_xor_line(split, sa->totrct.ymin, split, sa->totrct.ymax);
2187                         glutil_draw_front_xor_line(split-1, sa->totrct.ymin, split-1, sa->totrct.ymax);
2188                 }
2189         }
2190 }
2191
2192 static void splitarea_interactive(ScrArea *area, ScrEdge *onedge)
2193 {
2194         ScrArea *sa= area;
2195         float fac;
2196         unsigned short event;
2197         short ok= 0, val, split = 0, mval[2], mvalo[2], first= 1;
2198         char dir;
2199         
2200         if(sa->win==0) return;
2201         if(sa->full) return;
2202
2203         dir= scredge_is_horizontal(onedge)?'v':'h';
2204         
2205         mywinset(G.curscreen->mainwin);
2206         /* hoort al goede matrix te hebben */
2207
2208         /* rekening houden met grid en minsize */
2209         while(ok==0) {
2210                 getmouseco_sc(mval);
2211                 
2212                 if (first || mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
2213                         if (!first) {
2214                                 scrarea_draw_splitpoint(sa, dir, fac);
2215                         }
2216
2217                         if(dir=='h') {
2218                                 fac= mval[1]- (sa->v1->vec.y);
2219                                 fac/= sa->v2->vec.y- sa->v1->vec.y;
2220                         } else {
2221                                 fac= mval[0]- sa->v1->vec.x;
2222                                 fac/= sa->v4->vec.x- sa->v1->vec.x;
2223                         }
2224
2225                         split= testsplitpoint(sa, dir, fac);
2226                         if (split) {
2227                                 scrarea_draw_splitpoint(sa, dir, fac);
2228                         } else {
2229                                 ok= -1;
2230                         }
2231
2232                         mvalo[0]= mval[0];
2233                         mvalo[1]= mval[1];
2234                         first= 0;                       
2235                 }
2236                 
2237                 event= extern_qread(&val);
2238                 if(val && event==LEFTMOUSE) {
2239                         if(dir=='h') {
2240                                 fac= split- (sa->v1->vec.y);
2241                                 fac/= sa->v2->vec.y- sa->v1->vec.y;
2242                         }
2243                         else {
2244                                 fac= split- sa->v1->vec.x;
2245                                 fac/= sa->v4->vec.x- sa->v1->vec.x;
2246                         }
2247                         ok= 1;
2248                 }
2249                 if(val && event==ESCKEY) {
2250                         ok= -1;
2251                 }
2252         }
2253
2254         if (!first) {
2255                 scrarea_draw_splitpoint(sa, dir, fac);
2256         }
2257
2258         if(ok==1) {
2259                 splitarea(sa, dir, fac);
2260                 mainqenter(DRAWEDGES, 1);
2261                 dodrawscreen= 1;                /* patch! even gets lost,,,? */
2262         }
2263 }
2264
2265 View3D *find_biggest_view3d(void)
2266 {
2267         ScrArea *sa= find_biggest_area_of_type(SPACE_VIEW3D);
2268         
2269         if (sa) {
2270                 return (View3D*) sa->spacedata.first;
2271         } else {
2272                 return NULL;
2273         }
2274 }
2275
2276 ScrArea *find_biggest_area_of_type(int spacecode)
2277 {
2278         ScrArea *sa, *biggest= NULL;
2279         int bigsize;
2280         
2281         for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
2282                 if (spacecode==0 || sa->spacetype==spacecode) {
2283                         int x= sa->v3->vec.x - sa->v1->vec.x;
2284                         int y= sa->v3->vec.y - sa->v1->vec.y;
2285                         int size= x*x + y*y;
2286                 
2287                         if (!biggest || size>bigsize) {
2288                                 biggest= sa;
2289                                 bigsize= size;
2290                         }
2291                 }
2292         }
2293         
2294         return biggest;
2295 }
2296
2297 ScrArea *find_biggest_area(void)
2298 {
2299         return find_biggest_area_of_type(0);
2300 }
2301
2302 static void select_connected_scredge(bScreen *sc, ScrEdge *edge)
2303 {
2304         ScrEdge *se;
2305         ScrVert *sv;
2306         int oneselected;
2307         char dir;
2308         
2309         /* select connected, alleen in de juiste richting */
2310         /* 'dir' is de richting van de EDGE */
2311
2312         if(edge->v1->vec.x==edge->v2->vec.x) dir= 'v';
2313         else dir= 'h';
2314
2315         sv= sc->vertbase.first;
2316         while(sv) {
2317                 sv->flag= 0;
2318                 sv= sv->next;
2319         }
2320
2321         edge->v1->flag= 1;
2322         edge->v2->flag= 1;
2323
2324         oneselected= 1;
2325         while(oneselected) {
2326                 se= sc->edgebase.first;
2327                 oneselected= 0;
2328                 while(se) {
2329                         if(se->v1->flag + se->v2->flag==1) {
2330                                 if(dir=='h') if(se->v1->vec.y==se->v2->vec.y) {
2331                                         se->v1->flag= se->v2->flag= 1;
2332                                         oneselected= 1;
2333                                 }
2334                                 if(dir=='v') if(se->v1->vec.x==se->v2->vec.x) {
2335                                         se->v1->flag= se->v2->flag= 1;
2336                                         oneselected= 1;
2337                                 }
2338                         }
2339                         se= se->next;
2340                 }
2341         }
2342 }
2343
2344 void test_scale_screen(bScreen *sc)
2345 /* testen of screenvertices vergroot/verkleind moeten worden */
2346 /* testen of offset nog klopt */
2347 {
2348         ScrVert *sv=0;
2349         ScrEdge *se;
2350         ScrArea *sa, *san;
2351         int yval;
2352         float facx, facy, tempf, min[2], max[2];
2353
2354         sc->startx= prefstax;
2355         sc->starty= prefstay;
2356         sc->endx= prefstax+prefsizx-1;
2357         sc->endy= prefstay+prefsizy-1;
2358
2359         /* calculate size */
2360         sv= sc->vertbase.first;
2361         min[0]= min[1]= 0.0;
2362         max[0]= sc->sizex;
2363         max[1]= sc->sizey;
2364         while(sv) {
2365                 min[0]= MIN2(min[0], sv->vec.x);
2366                 min[1]= MIN2(min[1], sv->vec.y);
2367                 max[0]= MAX2(max[0], sv->vec.x);
2368                 max[1]= MAX2(max[1], sv->vec.y);
2369                 sv= sv->next;
2370         }
2371
2372         /* always make 0.0 left under */
2373         sv= sc->vertbase.first;
2374         while(sv) {
2375                 sv->vec.x -= min[0];
2376                 sv->vec.y -= min[1];
2377                 sv= sv->next;
2378         }
2379         
2380
2381         sc->sizex= max[0]-min[0];
2382         sc->sizey= max[1]-min[1];
2383
2384         if(sc->sizex!= prefsizx || sc->sizey!= prefsizy) {
2385                 facx= prefsizx;
2386                 facx/= (float)sc->sizex;
2387                 facy= prefsizy;
2388                 facy/= (float)sc->sizey;
2389
2390                 /* make sure it fits! */
2391                 sv= sc->vertbase.first;
2392                 while(sv) {
2393                         tempf= ((float)sv->vec.x)*facx;
2394                         sv->vec.x= (short)(tempf+0.5);
2395                         sv->vec.x+= AREAGRID-1;
2396                         sv->vec.x-=  (sv->vec.x % AREAGRID); 
2397                         
2398                         CLAMP(sv->vec.x, 0, prefsizx);
2399
2400                         tempf= ((float)sv->vec.y )*facy;
2401                         sv->vec.y= (short)(tempf+0.5);
2402                         sv->vec.y+= AREAGRID-1;
2403                         sv->vec.y-=  (sv->vec.y % AREAGRID); 
2404                         
2405                         CLAMP(sv->vec.y, 0, prefsizy);
2406
2407                         sv= sv->next;
2408                 }
2409                 
2410                 sc->sizex= prefsizx;
2411                 sc->sizey= prefsizy;
2412         }
2413
2414         /* test for collapsed areas. This could happen in some blender version... */
2415         sa= sc->areabase.first;
2416         while(sa) {
2417                 san= sa->next;
2418                 if(sa->v1==sa->v2 || sa->v3==sa->v4 || sa->v2==sa->v3) {
2419                         del_area(sa);
2420                         BLI_remlink(&sc->areabase, sa);
2421                         MEM_freeN(sa);
2422                 }
2423                 sa= san;
2424         }
2425
2426         /* make each window at least HEADERY high */
2427
2428         sa= sc->areabase.first;
2429         while(sa) {
2430
2431                 if(sa->v1->vec.y+HEADERY > sa->v2->vec.y) {
2432                         /* lower edge */
2433                         se= screen_findedge(sc, sa->v4, sa->v1);
2434                         if(se && sa->v1!=sa->v2 ) {
2435                                 select_connected_scredge(sc, se);
2436                                 
2437                                 /* all selected vertices get the right offset */
2438                                 yval= sa->v2->vec.y-HEADERY;
2439                                 sv= sc->vertbase.first;
2440                                 while(sv) {
2441                                         /* if is a collapsed area */
2442                                         if(sv!=sa->v2 && sv!=sa->v3) {
2443                                                 if(sv->flag) sv->vec.y= yval;
2444                                         }
2445                                         sv= sv->next;
2446                                 }
2447                         }
2448                 }
2449
2450                 sa= sa->next;
2451         }
2452
2453 }
2454
2455 static void draw_front_xor_dirdist_line(char dir, int dist, int start, int end)
2456 {
2457         if (dir=='h') {
2458                 glutil_draw_front_xor_line(start, dist, end, dist);
2459                 glutil_draw_front_xor_line(start, dist+1, end, dist+1);
2460         } else {
2461                 glutil_draw_front_xor_line(dist, start, dist, end);
2462                 glutil_draw_front_xor_line(dist+1, start, dist+1, end);
2463         }
2464 }
2465
2466 static void moveareas(ScrEdge *edge)
2467 {
2468         ScrVert *v1;
2469         ScrArea *sa;
2470         short mvalo[2];
2471         short edge_start, edge_end, edge_position;
2472         short bigger, smaller, headery, areaminy;
2473         int delta, doit;
2474         char dir;
2475         
2476         if(edge->border) return;
2477
2478         dir= scredge_is_horizontal(edge)?'h':'v';
2479         
2480         select_connected_scredge(G.curscreen, edge);
2481
2482         edge_position= (dir=='h')?edge->v1->vec.y:edge->v1->vec.x;
2483         edge_start= 10000;
2484         edge_end= -10000;
2485         for (v1= G.curscreen->vertbase.first; v1; v1= v1->next) {
2486                 if (v1->flag) {
2487                         if (dir=='h') {
2488                                 edge_start= MIN2(edge_start, v1->vec.x);
2489                                 edge_end= MAX2(edge_end, v1->vec.x);
2490                         } else {
2491                                 edge_start= MIN2(edge_start, v1->vec.y);
2492                                 edge_end= MAX2(edge_end, v1->vec.y);
2493                         }
2494                 }
2495         }
2496
2497         /* nu zijn alle vertices met 'flag==1' degene die verplaatst kunnen worden. */
2498         /* we lopen de areas af en testen vrije ruimte met MINSIZE */
2499         bigger= smaller= 10000;
2500         sa= G.curscreen->areabase.first;
2501         while(sa) {
2502                 if(dir=='h') {  /* als top of down edge select, test hoogte */
2503                         if(sa->headertype) {
2504                                 headery= HEADERY;
2505                                 areaminy= AREAMINY;
2506                         }
2507                         else {
2508                                 headery= 0;
2509                                 areaminy= EDGEWIDTH;
2510                         }
2511
2512                         if(sa->v1->flag && sa->v4->flag) {
2513                                 int y1;
2514                                 if(sa->v2->vec.y==G.curscreen->sizey-1) /* bovenste edge */
2515                                         y1= sa->v2->vec.y - sa->v1->vec.y-headery-EDGEWIDTH;
2516                                 else 
2517                                         y1= sa->v2->vec.y - sa->v1->vec.y-areaminy;
2518                                 bigger= MIN2(bigger, y1);
2519                         }
2520                         else if(sa->v2->flag && sa->v3->flag) {
2521                                 int y1;
2522                                 if(sa->v1->vec.y==0)    /* onderste edge */
2523                                         y1= sa->v2->vec.y - sa->v1->vec.y-headery-EDGEWIDTH;
2524                                 else
2525                                         y1= sa->v2->vec.y - sa->v1->vec.y-areaminy;
2526                                 smaller= MIN2(smaller, y1);
2527                         }
2528                 }
2529                 else {  /* als left of right edge select, test breedte */
2530                         if(sa->v1->flag && sa->v2->flag) {
2531                                 int x1= sa->v4->vec.x - sa->v1->vec.x-AREAMINX;
2532                                 bigger= MIN2(bigger, x1);
2533                         }
2534                         else if(sa->v3->flag && sa->v4->flag) {
2535                                 int x1= sa->v4->vec.x - sa->v1->vec.x-AREAMINX;
2536                                 smaller= MIN2(smaller, x1);
2537                         }
2538                 }
2539                 sa= sa->next;
2540         }
2541         
2542         mywinset(G.curscreen->mainwin);
2543
2544         doit= delta= 0;
2545         getmouseco_sc(mvalo);
2546         draw_front_xor_dirdist_line(dir, edge_position+delta, edge_start, edge_end);
2547         while (!doit) {
2548                 short val;
2549                 unsigned short event= extern_qread(&val);
2550                 
2551                 if (event==MOUSEY) {
2552                         short mval[2];
2553                         
2554                         getmouseco_sc(mval);
2555                         
2556                         draw_front_xor_dirdist_line(dir, edge_position+delta, edge_start, edge_end);
2557
2558                         delta= (dir=='h')?(mval[1]-mvalo[1]):(mval[0]-mvalo[0]);
2559                         delta= CLAMPIS(delta, -smaller, bigger);
2560                         
2561                         draw_front_xor_dirdist_line(dir, edge_position+delta, edge_start, edge_end);
2562                 } else if (event==LEFTMOUSE) {
2563                         doit= 1;
2564                 } else if (val) {
2565                         if (ELEM(event, ESCKEY, RIGHTMOUSE))
2566                                 doit= -1;
2567                         else if (ELEM(event, SPACEKEY, RETKEY))
2568                                 doit= 1;
2569                 }
2570         }
2571         draw_front_xor_dirdist_line(dir, edge_position+delta, edge_start, edge_end);
2572
2573         if (doit==1) {
2574                 for (v1= G.curscreen->vertbase.first; v1; v1= v1->next) {
2575                         if (v1->flag) {
2576                                         /* zo is AREAGRID netjes */
2577                                 if((dir=='v') && v1->vec.x>0 && v1->vec.x<G.curscreen->sizex-1) {
2578                                         v1->vec.x+= delta;
2579                                         if(delta != bigger && delta != -smaller) v1->vec.x-= (v1->vec.x % AREAGRID);
2580                                 }
2581                                 if((dir=='h') && v1->vec.y>0 && v1->vec.y<G.curscreen->sizey-1) {
2582                                         v1->vec.y+= delta;
2583                                         
2584                                         /* with these lines commented out you can pull the top bar exact to the screen border. */
2585                                         /* if(delta != bigger && delta != -smaller) { */
2586                                                 v1->vec.y+= AREAGRID-1;
2587                                                 v1->vec.y-= (v1->vec.y % AREAGRID);
2588                                         
2589                                         /* } */
2590                                 }
2591                         }
2592                         v1->flag= 0;
2593                 }
2594                 
2595                 removedouble_scrverts();
2596                 removedouble_scredges();
2597                 testareas();
2598         }
2599         
2600         glDrawBuffer(GL_BACK);
2601         mainqenter(DRAWEDGES, 1);
2602         dodrawscreen= 1;                /* patch! even gets lost,,,? */
2603 }
2604
2605 static void scrollheader(ScrArea *area)
2606 {
2607         short mval[2], mvalo[2];
2608         
2609         if(area->headbutlen<area->winx) {
2610                 area->headbutofs= 0;
2611         }
2612         else if(area->headbutofs+area->winx > area->headbutlen) {
2613                 area->headbutofs= area->headbutlen-area->winx;
2614         }
2615
2616         getmouseco_sc(mvalo);
2617
2618         while(get_mbut() & M_MOUSE) {
2619                 getmouseco_sc(mval);
2620                 if(mval[0]!=mvalo[0]) {
2621                         area->headbutofs-= (mval[0]-mvalo[0]);
2622
2623                         if(area->headbutlen-area->winx < area->headbutofs) area->headbutofs= area->headbutlen-area->winx;
2624                         if(area->headbutofs<0) area->headbutofs= 0;
2625
2626                         scrarea_do_headchange(area);
2627                         scrarea_do_headdraw(area);
2628
2629                         screen_swapbuffers();
2630                         
2631                         mvalo[0]= mval[0];
2632                 } else {
2633                         BIF_wait_for_statechange();
2634                 }
2635         }
2636 }
2637
2638 int select_area(int spacetype)
2639 {
2640         /* vanuit editroutines aanroepen, als er meer area's
2641          * zijn van type 'spacetype' kan er een area aangegeven worden
2642          */
2643         ScrArea *sa, *sact = NULL;
2644         int tot=0;
2645         unsigned short event = 0;
2646         short val, mval[2];
2647         
2648         sa= G.curscreen->areabase.first;
2649         while(sa) {
2650                 if(sa->spacetype==spacetype) {
2651                         sact= sa;
2652                         tot++;
2653                 }
2654                 sa= sa->next;
2655         } 
2656         
2657         if(tot==0) {
2658                 error("Can't do this! Open correct window");
2659                 return 0;
2660         }
2661         
2662         if(tot==1) {
2663                 if(curarea!=sact) areawinset(sact->win);
2664                 return 1;
2665         }
2666         else if(tot>1) {
2667                 set_cursor(CURSOR_HELP);
2668                 while(1) {
2669                         event= extern_qread(&val);
2670                         
2671                         if (val) {
2672                                 if(event==ESCKEY) break;
2673                                 if(event==LEFTMOUSE) break;
2674                                 if(event==SPACEKEY) break;
2675                         } else {
2676                                 BIF_wait_for_statechange();
2677                         }
2678                 }
2679                 screen_set_cursor(G.curscreen);
2680                 
2681                 /* recalculate winakt */
2682                 getmouseco_sc(mval);
2683                 
2684                 if(event==LEFTMOUSE) {
2685                         ScrArea *sa= screen_find_area_for_pt(G.curscreen, mval);
2686                         
2687                         if (sa &&sa->spacetype==spacetype) {
2688                                 G.curscreen->winakt= sa->win;
2689                                 areawinset(G.curscreen->winakt);
2690                         } else {
2691                                 error("wrong window");
2692                                 return 0;
2693                         }
2694                 }
2695         }
2696         
2697         if(event==LEFTMOUSE) return 1;
2698         else return 0;
2699 }
2700
2701 /* ************  END JOIN/SPLIT/MOVE ************** */
2702 /* **************** DRAW SCREENEDGES ***************** */
2703
2704 #define EDGE_EXTEND 3
2705
2706 void drawedge(short x1, short y1, short x2, short y2)
2707 {
2708         static unsigned int edcol[EDGEWIDTH]= {0x0, 0x505050, 0x909090, 0xF0F0F0, 0x0};
2709         int a;
2710         
2711         if(x1==x2) {            /* vertical */
2712                 if (y2<y1)
2713                         y1^= y2^= y1^= y2;
2714                 
2715                 if (y1==0) y1-= EDGE_EXTEND;
2716                 if (y2==G.curscreen->sizey) y2+= EDGE_EXTEND;
2717                 
2718                 x1+= EDGEWIDTH2;
2719                 x2+= EDGEWIDTH2;
2720
2721                 glBegin(GL_LINES);              
2722                 for(a=0; a<EDGEWIDTH; a++) {
2723                         int rounding= abs(a-EDGEWIDTH2);
2724                         
2725                         cpack(edcol[a]);
2726                         glVertex2i(x1-a, y1+rounding);
2727                         glVertex2i(x2-a, y2-rounding);
2728                 }
2729                 glEnd();
2730         }
2731         else {                          /* horizontal */
2732                 if (x2<x1)
2733                         x1^= x2^= x1^= x2;
2734                 
2735                 if (x1==0) x1-= EDGE_EXTEND;
2736                 if (x2==G.curscreen->sizex) x2+= EDGE_EXTEND;
2737
2738                 y1-= EDGEWIDTH2;
2739                 y2-= EDGEWIDTH2;
2740                 
2741                 glBegin(GL_LINES);
2742                 for(a=0; a<EDGEWIDTH; a++) {
2743                         int rounding= abs(a-EDGEWIDTH2);
2744                         
2745                         cpack(edcol[a]);
2746                         glVertex2i(x1+rounding, y1+a);
2747                         glVertex2i(x2-rounding, y2+a);
2748                 }
2749                 glEnd();
2750         }
2751 }
2752
2753 static void drawscredge(ScrEdge *se)
2754 {
2755         bScreen *sc;
2756         vec2s *v1, *v2;
2757         
2758         sc= G.curscreen;
2759         
2760         v1= &(se->v1->vec);
2761         v2= &(se->v2->vec);
2762         
2763         /* borders screen niet tekenen */
2764         /* vanwege resolutie verschillen (PC/SGI files) de linit een
2765          * beetje afronden?
2766          */
2767         se->border= 1;
2768         if(v1->x<=1 && v2->x<=1) return;
2769         if(v1->x>=sc->sizex-2 && v2->x>=sc->sizex-2) return;
2770         if(v1->y<=1 && v2->y<=1) return;
2771         if(v1->y>=sc->sizey-2 && v2->y>=sc->sizey-2) return;
2772         se->border= 0;
2773
2774         drawedge(v1->x, v1->y, v2->x, v2->y);
2775 }
2776
2777 void drawscreen(void)
2778 {
2779         ScrEdge *se;
2780         
2781         mywinset(G.curscreen->mainwin);
2782         myortho2(-0.5, (float)G.curscreen->sizex-0.5, -0.5, (float)G.curscreen->sizey-0.5);
2783
2784         /* two times, because there is no 'win_swap' for this  available */
2785         glDrawBuffer(GL_FRONT);
2786         se= G.curscreen->edgebase.first;
2787         while(se) {
2788                 drawscredge(se);
2789                 se= se->next;
2790         }
2791
2792         glDrawBuffer(GL_BACK);
2793         se= G.curscreen->edgebase.first;
2794         while(se) {
2795                 drawscredge(se);
2796                 se= se->next;
2797         }
2798 }
2799
2800 /* ********************************* */
2801
2802 bScreen *default_twosplit() 
2803 {
2804         bScreen *sc= addscreen("screen");
2805         ScrArea *sa;
2806
2807         splitarea( (ScrArea *)sc->areabase.first, 'h', 0.99);
2808         sa= sc->areabase.first;
2809         newspace(sa, SPACE_VIEW3D);
2810         newspace(sa->next, SPACE_INFO);
2811         
2812         return sc;
2813 }
2814
2815 void initscreen(void)
2816 {
2817         default_twosplit();
2818 }
2819
2820 /***/
2821
2822 void screen_draw_info_text(bScreen *sc, char *text) {
2823         Window *oldactwin= winlay_get_active_window();
2824         ScrArea *sa;
2825         
2826                 /*
2827                  * Because this is called from within rendering
2828                  * internals it is possible our window is not
2829                  * active.
2830                  */
2831         window_make_active(mainwin);
2832         
2833         for (sa= sc->areabase.first; sa; sa= sa->next) {
2834                 if (sa->spacetype==SPACE_INFO) {
2835                         int x= sa->headbutlen - 28;
2836                         int y= 6;
2837                         
2838                         areawinset(sa->headwin);
2839                         glDrawBuffer(GL_FRONT);
2840
2841                         cpack(0xA08060);
2842                         glRecti(x-11,  y-6,  x+55,  y+13);
2843                         
2844                         cpack(0x909090);
2845                         glRecti(x+55,  y-6,  x+1280,  y+14);
2846                         
2847                         cpack(0x0);
2848                         glRasterPos2i(x,  y);
2849                         BMF_DrawString(G.fonts, text);
2850                         
2851                         glFinish();
2852                         glDrawBuffer(GL_BACK);
2853                         
2854                         sa->head_swap= WIN_FRONT_OK;
2855                 }
2856         }
2857         
2858         if (oldactwin && oldactwin!=mainwin) window_make_active(oldactwin);
2859 }
2860
2861 static int curcursor;
2862
2863 int get_cursor(void) {
2864         return curcursor;
2865 }
2866
2867 void set_cursor(int curs) {
2868         if (!(R.flag & R_RENDERING)) {
2869                 if (curs!=curcursor) {
2870                         curcursor= curs;
2871                         window_set_cursor(mainwin, curs);
2872                 }
2873         }
2874 }
2875
2876 void unlink_screen(bScreen *sc) {
2877         ScrArea *sa;
2878         
2879         for (sa= sc->areabase.first; sa; sa= sa->next)  
2880                 del_area(sa);
2881 }
2882
2883 void warp_pointer(int x, int y)
2884 {
2885         window_warp_pointer(mainwin, x, y);
2886 }
2887
2888 void set_timecursor(int nr)
2889 {
2890                 /* 10 8x8 digits */
2891         static char number_bitmaps[10][8]= {
2892                 {0,  56,  68,  68,  68,  68,  68,  56}, 
2893                 {0,  24,  16,  16,  16,  16,  16,  56}, 
2894                 {0,  60,  66,  32,  16,   8,   4, 126}, 
2895                 {0, 124,  32,  16,  56,  64,  66,  60}, 
2896                 {0,  32,  48,  40,  36, 126,  32,  32}, 
2897                 {0, 124,   4,  60,  64,  64,  68,  56}, 
2898                 {0,  56,   4,   4,  60,  68,  68,  56}, 
2899                 {0, 124,  64,  32,  16,   8,   8,   8}, 
2900                 {0,  60,  66,  66,  60,  66,  66,  60}, 
2901                 {0,  56,  68,  68, 120,  64,  68,  56} 
2902         };
2903         unsigned char mask[16][2];
2904         unsigned char bitmap[16][2];
2905         int i, idx;
2906
2907         memset(&bitmap, 0x00, sizeof(bitmap));
2908         memset(&mask, 0xFF, sizeof(mask));
2909         
2910                 /* print number bottom right justified */
2911         for (idx= 3; nr && idx>=0; idx--) {
2912                 char *digit= number_bitmaps[nr%10];
2913                 int x = idx%2;
2914                 int y = idx/2;
2915                 
2916                 for (i=0; i<8; i++)
2917                         bitmap[i + y*8][x]= digit[i];
2918                 nr/= 10;
2919         }
2920
2921         curcursor= CURSOR_NONE;
2922         window_set_custom_cursor(mainwin, mask, bitmap);
2923         BIF_renderwin_set_custom_cursor(mask, bitmap);
2924 }
2925