Merged changes in the trunk up to revision 26439.
[blender.git] / source / blender / editors / screen / screen_ops.c
index 4a002088c3dedf5b569e6ff92060483a2cf3caae..4394893ff69b11c6fa551770a1fbad70dedb8ba8 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <math.h>
 #include <string.h>
+#include <stddef.h>
 
 #include <GL/glew.h>
 
 #define KM_MODAL_STEP10                3
 #define KM_MODAL_STEP10_OFF    4
 
+#if defined(__APPLE__) && (PARALLEL == 1) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 2)
+/* ************** libgomp (Apple gcc 4.2.1) TLS bug workaround *************** */
+#include <pthread.h>
+extern pthread_key_t gomp_tls_key;
+static void *thread_tls_data;
+#endif
 /* ************** Exported Poll tests ********************** */
 
 int ED_operator_regionactive(bContext *C)
@@ -180,10 +187,10 @@ int ED_operator_buttons_active(bContext *C)
 int ED_operator_node_active(bContext *C)
 {
        SpaceNode *snode= CTX_wm_space_node(C);
-
+       
        if(snode && snode->edittree)
                return 1;
-
+       
        return 0;
 }
 
@@ -218,6 +225,12 @@ int ED_operator_object_active(bContext *C)
        return NULL != CTX_data_active_object(C);
 }
 
+int ED_operator_object_active_editable(bContext *C)
+{
+       Object *ob=CTX_data_active_object(C);
+       return ((ob != NULL) && !(ob->id.lib));
+}
+
 int ED_operator_editmesh(bContext *C)
 {
        Object *obedit= CTX_data_edit_object(C);
@@ -226,6 +239,11 @@ int ED_operator_editmesh(bContext *C)
        return 0;
 }
 
+int ED_operator_editmesh_view3d(bContext *C)
+{
+       return ED_operator_editmesh(C) && ED_operator_view3d_active(C);
+}
+
 int ED_operator_editarmature(bContext *C)
 {
        Object *obedit= CTX_data_edit_object(C);
@@ -241,7 +259,7 @@ int ED_operator_posemode(bContext *C)
        
        if ((obact != obedit) && (obact) && (obact->type==OB_ARMATURE))
                return (obact->mode & OB_MODE_POSE)!=0;
-               
+       
        return 0;
 }
 
@@ -250,15 +268,15 @@ int ED_operator_uvedit(bContext *C)
 {
        Object *obedit= CTX_data_edit_object(C);
        EditMesh *em= NULL;
-
+       
        if(obedit && obedit->type==OB_MESH)
                em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
-
+       
        if(em && (em->faces.first) && (CustomData_has_layer(&em->fdata, CD_MTFACE))) {
                BKE_mesh_end_editmesh(obedit->data, em);
                return 1;
        }
-
+       
        if(obedit)
                BKE_mesh_end_editmesh(obedit->data, em);
        return 0;
@@ -268,15 +286,15 @@ int ED_operator_uvmap(bContext *C)
 {
        Object *obedit= CTX_data_edit_object(C);
        EditMesh *em= NULL;
-
+       
        if(obedit && obedit->type==OB_MESH)
                em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
-
+       
        if(em && (em->faces.first)) {
                BKE_mesh_end_editmesh(obedit->data, em);
                return 1;
        }
-
+       
        if(obedit)
                BKE_mesh_end_editmesh(obedit->data, em);
        return 0;
@@ -334,27 +352,27 @@ int ED_operator_editmball(bContext *C)
 /* *************************** action zone operator ************************** */
 
 /* operator state vars used:  
      none
-
-functions:
-
      apply() set actionzone event
-
      exit()  free customdata
-       
-callbacks:
-
      exec()  never used
-
      invoke() check if in zone  
              add customdata, put mouseco and area in it
              add modal handler
-
      modal() accept modal events while doing it
              call apply() with gesture info, active window, nonactive window
              call exit() and remove handler when LMB confirm
-
-*/
+ none
+ functions:
+ apply() set actionzone event
exit()        free customdata
+ callbacks:
exec()        never used
+ invoke() check if in zone  
+ add customdata, put mouseco and area in it
+ add modal handler
modal()       accept modal events while doing it
+ call apply() with gesture info, active window, nonactive window
+ call exit() and remove handler when LMB confirm
+ */
 
 typedef struct sActionzoneData {
        ScrArea *sa1, *sa2;
@@ -388,7 +406,7 @@ static int actionzone_area_poll(bContext *C)
                
                for(az= sa->actionzones.first; az; az= az->next)
                        if(BLI_in_rcti(&az->rect, x, y))
-                          return 1;
+                               return 1;
        }       
        return 0;
 }
@@ -503,14 +521,14 @@ static int actionzone_modal(bContext *C, wmOperator *op, wmEvent *event)
                                
                                return OPERATOR_FINISHED;
                        }
-                               break;
+                       break;
                case ESCKEY:
                        actionzone_exit(C, op);
                        return OPERATOR_CANCELLED;
                case LEFTMOUSE:                         
                        actionzone_exit(C, op);
                        return OPERATOR_CANCELLED;
-
+                       
        }
        
        return OPERATOR_RUNNING_MODAL;
@@ -526,7 +544,7 @@ static void SCREEN_OT_actionzone(wmOperatorType *ot)
        ot->invoke= actionzone_invoke;
        ot->modal= actionzone_modal;
        ot->poll= actionzone_area_poll;
-
+       
        ot->flag= OPTYPE_BLOCKING;
        
        RNA_def_int(ot->srna, "modifier", 0, 0, 2, "modifier", "modifier state", 0, 2);
@@ -535,25 +553,25 @@ static void SCREEN_OT_actionzone(wmOperatorType *ot)
 /* ************** swap area operator *********************************** */
 
 /* operator state vars used:  
                                      sa1             start area
                                      sa2             area to swap with
-
      functions:
-
      init()   set custom data for operator, based on actionzone event custom data
-
      cancel()        cancel the operator
-
      exit()  cleanup, send notifier
-
      callbacks:
-
      invoke() gets called on shift+lmb drag in actionzone
           call init(), add handler
-
      modal()  accept modal events while doing it
-
-*/
sa1           start area
sa2           area to swap with
+ functions:
+ init()   set custom data for operator, based on actionzone event custom data
cancel()      cancel the operator
exit()        cleanup, send notifier
+ callbacks:
+ invoke() gets called on shift+lmb drag in actionzone
+ call init(), add handler
+ modal()  accept modal events while doing it
+ */
 
 typedef struct sAreaSwapData {
        ScrArea *sa1, *sa2;
@@ -563,15 +581,15 @@ static int area_swap_init(bContext *C, wmOperator *op, wmEvent *event)
 {
        sAreaSwapData *sd= NULL;
        sActionzoneData *sad= event->customdata;
-
+       
        if(sad==NULL || sad->sa1==NULL)
-                                       return 0;
+               return 0;
        
        sd= MEM_callocN(sizeof(sAreaSwapData), "sAreaSwapData");
        sd->sa1= sad->sa1;
        sd->sa2= sad->sa2;
        op->customdata= sd;
-
+       
        return 1;
 }
 
@@ -591,22 +609,22 @@ static int area_swap_cancel(bContext *C, wmOperator *op)
 
 static int area_swap_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
-
+       
        if(!area_swap_init(C, op, event))
                return OPERATOR_PASS_THROUGH;
-
+       
        /* add modal handler */
        WM_cursor_modal(CTX_wm_window(C), BC_SWAPAREA_CURSOR);
        WM_event_add_modal_handler(C, op);
        
        return OPERATOR_RUNNING_MODAL;
-
+       
 }
 
 static int area_swap_modal(bContext *C, wmOperator *op, wmEvent *event)
 {
        sActionzoneData *sad= op->customdata;
-
+       
        switch(event->type) {
                case MOUSEMOVE:
                        /* second area, for join */
@@ -615,19 +633,24 @@ static int area_swap_modal(bContext *C, wmOperator *op, wmEvent *event)
                case LEFTMOUSE: /* release LMB */
                        if(event->val==KM_RELEASE) {
                                if(!sad->sa2 || sad->sa1 == sad->sa2) {
-
+                                       
                                        return area_swap_cancel(C, op);
                                }
                                ED_area_swapspace(C, sad->sa1, sad->sa2);
-
+                               
                                area_swap_exit(C, op);
+                               
+#ifdef WM_FAST_DRAW
+                               ED_area_tag_redraw(sad->sa1);
+                               ED_area_tag_redraw(sad->sa2);
+#endif
 
                                WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
-
+                               
                                return OPERATOR_FINISHED;
                        }
                        break;
-
+                       
                case ESCKEY:
                        return area_swap_cancel(C, op);
        }
@@ -639,11 +662,11 @@ static void SCREEN_OT_area_swap(wmOperatorType *ot)
        ot->name= "Swap areas";
        ot->description= "Swap selected areas screen positions.";
        ot->idname= "SCREEN_OT_area_swap";
-
+       
        ot->invoke= area_swap_invoke;
        ot->modal= area_swap_modal;
        ot->poll= ED_operator_areaactive;
-
+       
        ot->flag= OPTYPE_BLOCKING;
 }
 
@@ -664,10 +687,10 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, wmEvent *event)
        /* XXX hrmf! */
        if(event->type==EVT_ACTIONZONE_AREA) {
                sActionzoneData *sad= event->customdata;
-
+               
                if(sad==NULL)
                        return OPERATOR_PASS_THROUGH;
-       
+               
                sa= sad->sa1;
        }
        
@@ -690,9 +713,13 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, wmEvent *event)
        /* copy area to new screen */
        area_copy_data((ScrArea *)newsc->areabase.first, sa, 0);
        
+#ifdef WM_FAST_DRAW
+       ED_area_tag_redraw((ScrArea *)newsc->areabase.first);
+#endif
+
        /* screen, areas init */
        WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
-
+       
        if(event->type==EVT_ACTIONZONE_AREA)
                actionzone_exit(C, op);
        
@@ -713,33 +740,33 @@ static void SCREEN_OT_area_dupli(wmOperatorType *ot)
 /* ************** move area edge operator *********************************** */
 
 /* operator state vars used:  
          x, y                        mouse coord near edge
          delta            movement of edge
-
      functions:
-
      init()   set default property values, find edge based on mouse coords, test
           if the edge can be moved, select edges, calculate min and max movement
-
      apply() apply delta on selection
-
      exit()  cleanup, send notifier
-
      cancel() cancel moving
-
      callbacks:
-
      exec()   execute without any user interaction, based on properties
           call init(), apply(), exit()
-
      invoke() gets called on mouse click near edge
           call init(), add handler
-
      modal()  accept modal events while doing it
                      call apply() with delta motion
           call exit() and remove handler
-
-*/
x, y                          mouse coord near edge
+ delta            movement of edge
+ functions:
+ init()   set default property values, find edge based on mouse coords, test
+ if the edge can be moved, select edges, calculate min and max movement
apply()       apply delta on selection
exit()        cleanup, send notifier
+ cancel() cancel moving
+ callbacks:
+ exec()   execute without any user interaction, based on properties
+ call init(), apply(), exit()
+ invoke() gets called on mouse click near edge
+ call init(), add handler
+ modal()  accept modal events while doing it
+ call apply() with delta motion
+ call exit() and remove handler
+ */
 
 typedef struct sAreaMoveData {
        int bigger, smaller, origval, step;
@@ -784,25 +811,25 @@ static int area_move_init (bContext *C, wmOperator *op)
        ScrEdge *actedge;
        sAreaMoveData *md;
        int x, y;
-
+       
        /* required properties */
        x= RNA_int_get(op->ptr, "x");
        y= RNA_int_get(op->ptr, "y");
-
+       
        /* setup */
        actedge= screen_find_active_scredge(sc, x, y);
        if(actedge==NULL) return 0;
-
+       
        md= MEM_callocN(sizeof(sAreaMoveData), "sAreaMoveData");
        op->customdata= md;
-
+       
        md->dir= scredge_is_horizontal(actedge)?'h':'v';
        if(md->dir=='h') md->origval= actedge->v1->vec.y;
        else md->origval= actedge->v1->vec.x;
        
        select_connected_scredge(sc, actedge);
        /* now all vertices with 'flag==1' are the ones that can be moved. */
-
+       
        area_move_set_limits(sc, md->dir, &md->bigger, &md->smaller);
        
        return 1;
@@ -826,7 +853,7 @@ static void area_move_apply_do(bContext *C, int origval, int delta, int dir, int
                        }
                        if((dir=='h') && v1->vec.y>0 && v1->vec.y<win->sizey-1) {
                                v1->vec.y= origval + delta;
-
+                               
                                v1->vec.y+= AREAGRID-1;
                                v1->vec.y-= (v1->vec.y % AREAGRID);
                                
@@ -836,8 +863,16 @@ static void area_move_apply_do(bContext *C, int origval, int delta, int dir, int
                        }
                }
        }
+#ifdef WM_FAST_DRAW
+       {
+               ScrArea *sa;
+               for(sa= sc->areabase.first; sa; sa= sa->next)
+                       if(sa->v1->flag || sa->v2->flag || sa->v3->flag || sa->v4->flag)
+                               ED_area_tag_redraw(sa);
+       }
 
-       WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
+#endif
+       WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL); /* redraw everything */
 }
 
 static void area_move_apply(bContext *C, wmOperator *op)
@@ -876,7 +911,7 @@ static int area_move_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
        RNA_int_set(op->ptr, "x", event->x);
        RNA_int_set(op->ptr, "y", event->y);
-
+       
        if(!area_move_init(C, op)) 
                return OPERATOR_PASS_THROUGH;
        
@@ -888,11 +923,11 @@ static int area_move_invoke(bContext *C, wmOperator *op, wmEvent *event)
 
 static int area_move_cancel(bContext *C, wmOperator *op)
 {
-
+       
        RNA_int_set(op->ptr, "delta", 0);
        area_move_apply(C, op);
        area_move_exit(C, op);
-
+       
        return OPERATOR_CANCELLED;
 }
 
@@ -901,7 +936,7 @@ static int area_move_modal(bContext *C, wmOperator *op, wmEvent *event)
 {
        sAreaMoveData *md= op->customdata;
        int delta, x, y;
-
+       
        /* execute the events */
        switch(event->type) {
                case MOUSEMOVE:
@@ -912,7 +947,7 @@ static int area_move_modal(bContext *C, wmOperator *op, wmEvent *event)
                        delta= (md->dir == 'v')? event->x - x: event->y - y;
                        if(md->step) delta= delta - (delta % md->step);
                        RNA_int_set(op->ptr, "delta", delta);
-
+                       
                        area_move_apply(C, op);
                        break;
                        
@@ -922,7 +957,7 @@ static int area_move_modal(bContext *C, wmOperator *op, wmEvent *event)
                                case KM_MODAL_APPLY:
                                        area_move_exit(C, op);
                                        return OPERATOR_FINISHED;
-
+                                       
                                case KM_MODAL_CANCEL:
                                        return area_move_cancel(C, op);
                                        
@@ -944,15 +979,15 @@ static void SCREEN_OT_area_move(wmOperatorType *ot)
        ot->name= "Move area edges";
        ot->description= "Move selected area edges.";
        ot->idname= "SCREEN_OT_area_move";
-
+       
        ot->exec= area_move_exec;
        ot->invoke= area_move_invoke;
        ot->cancel= area_move_cancel;
        ot->modal= area_move_modal;
        ot->poll= ED_operator_screen_mainwinactive; /* when mouse is over area-edge */
-
+       
        ot->flag= OPTYPE_BLOCKING;
-
+       
        /* rna */
        RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX);
        RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX);
@@ -962,56 +997,56 @@ static void SCREEN_OT_area_move(wmOperatorType *ot)
 /* ************** split area operator *********************************** */
 
 /* 
-operator state vars:  
      fac              spit point
      dir              direction 'v' or 'h'
-
-operator customdata:
      area                    pointer to (active) area
      x, y                    last used mouse pos
      (more, see below)
-
-functions:
-
      init()   set default property values, find area based on context
-
      apply() split area based on state vars
-
      exit()  cleanup, send notifier
-
      cancel() remove duplicated area
-
-callbacks:
-
      exec()   execute without any user interaction, based on state vars
           call init(), apply(), exit()
-
      invoke() gets called on mouse click in action-widget
           call init(), add modal handler
                      call apply() with initial motion
-
      modal()  accept modal events while doing it
           call move-areas code with delta motion
           call exit() or cancel() and remove handler
-
-*/
+ operator state vars:  
+ fac              spit point
+ dir              direction 'v' or 'h'
+ operator customdata:
area                          pointer to (active) area
x, y                  last used mouse pos
+ (more, see below)
+ functions:
+ init()   set default property values, find area based on context
apply()       split area based on state vars
exit()        cleanup, send notifier
+ cancel() remove duplicated area
+ callbacks:
+ exec()   execute without any user interaction, based on state vars
+ call init(), apply(), exit()
+ invoke() gets called on mouse click in action-widget
+ call init(), add modal handler
+ call apply() with initial motion
+ modal()  accept modal events while doing it
+ call move-areas code with delta motion
+ call exit() or cancel() and remove handler
+ */
 
 #define SPLIT_STARTED  1
 #define SPLIT_PROGRESS 2
 
 typedef struct sAreaSplitData
-{
-       int x, y;       /* last used mouse position */
-       
-       int origval;                    /* for move areas */
-       int bigger, smaller;    /* constraints for moving new edge */
-       int delta;                              /* delta move edge */
-       int origmin, origsize;  /* to calculate fac, for property storage */
-
-       ScrEdge *nedge;                 /* new edge */
-       ScrArea *sarea;                 /* start area */
-       ScrArea *narea;                 /* new area */
-} sAreaSplitData;
+       {
+               int x, y;       /* last used mouse position */
+               
+               int origval;                    /* for move areas */
+               int bigger, smaller;    /* constraints for moving new edge */
+               int delta;                              /* delta move edge */
+               int origmin, origsize;  /* to calculate fac, for property storage */
+               
+               ScrEdge *nedge;                 /* new edge */
+               ScrArea *sarea;                 /* start area */
+               ScrArea *narea;                 /* new area */
+       } sAreaSplitData;
 
 /* generic init, no UI stuff here */
 static int area_split_init(bContext *C, wmOperator *op)
@@ -1029,7 +1064,7 @@ static int area_split_init(bContext *C, wmOperator *op)
        /* minimal size */
        if(dir=='v' && sa->winx < 2*AREAMINX) return 0;
        if(dir=='h' && sa->winy < 2*AREAMINY) return 0;
-          
+       
        /* custom data */
        sd= (sAreaSplitData*)MEM_callocN(sizeof (sAreaSplitData), "op_area_split");
        op->customdata= sd;
@@ -1066,7 +1101,7 @@ static ScrEdge *area_findsharededge(bScreen *screen, ScrArea *sa, ScrArea *sb)
        else if(sav1==sbv2 && sav4==sbv3) { /* sa on top of sb = S*/
                return screen_findedge(screen, sav1, sav4);
        }
-
+       
        return NULL;
 }
 
@@ -1081,24 +1116,28 @@ static int area_split_apply(bContext *C, wmOperator *op)
        
        fac= RNA_float_get(op->ptr, "factor");
        dir= RNA_enum_get(op->ptr, "direction");
-
+       
        sd->narea= area_split(CTX_wm_window(C), sc, sd->sarea, dir, fac);
        
        if(sd->narea) {
                ScrVert *sv;
                
                sd->nedge= area_findsharededge(sc, sd->sarea, sd->narea);
-       
+               
                /* select newly created edge, prepare for moving edge */
                for(sv= sc->vertbase.first; sv; sv= sv->next)
                        sv->flag = 0;
                
                sd->nedge->v1->flag= 1;
                sd->nedge->v2->flag= 1;
-
+               
                if(dir=='h') sd->origval= sd->nedge->v1->vec.y;
                else sd->origval= sd->nedge->v1->vec.x;
 
+#ifdef WM_FAST_DRAW
+               ED_area_tag_redraw(sd->sarea);
+               ED_area_tag_redraw(sd->narea);
+#endif
                WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
                
                return 1;
@@ -1110,12 +1149,18 @@ static int area_split_apply(bContext *C, wmOperator *op)
 static void area_split_exit(bContext *C, wmOperator *op)
 {
        if (op->customdata) {
+#ifdef WM_FAST_DRAW
+               sAreaSplitData *sd= (sAreaSplitData *)op->customdata;
+               if(sd->sarea) ED_area_tag_redraw(sd->sarea);
+               if(sd->narea) ED_area_tag_redraw(sd->narea);
+#endif
+
                MEM_freeN(op->customdata);
                op->customdata = NULL;
        }
        
        WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
-
+       
        /* this makes sure aligned edges will result in aligned grabbing */
        removedouble_scrverts(CTX_wm_screen(C));
        removedouble_scredges(CTX_wm_screen(C));
@@ -1130,7 +1175,7 @@ static int area_split_invoke(bContext *C, wmOperator *op, wmEvent *event)
        if(event->type==EVT_ACTIONZONE_AREA) {
                sActionzoneData *sad= event->customdata;
                int dir;
-
+               
                if(sad->modifier>0) {
                        return OPERATOR_PASS_THROUGH;
                }
@@ -1157,7 +1202,7 @@ static int area_split_invoke(bContext *C, wmOperator *op, wmEvent *event)
                        RNA_float_set(op->ptr, "factor", ((float)(event->y - sad->sa1->v1->vec.y)) / (float)sad->sa1->winy);
                }
                RNA_enum_set(op->ptr, "direction", dir);
-
+               
                /* general init, also non-UI case, adds customdata, sets area and defaults */
                if(!area_split_init(C, op))
                        return OPERATOR_PASS_THROUGH;
@@ -1203,7 +1248,7 @@ static int area_split_exec(bContext *C, wmOperator *op)
 static int area_split_cancel(bContext *C, wmOperator *op)
 {
        sAreaSplitData *sd= (sAreaSplitData *)op->customdata;
-
+       
        if (screen_area_join(C, CTX_wm_screen(C), sd->sarea, sd->narea)) {
                if (CTX_wm_area(C) == sd->narea) {
                        CTX_wm_area_set(C, NULL);
@@ -1212,7 +1257,7 @@ static int area_split_cancel(bContext *C, wmOperator *op)
                sd->narea = NULL;
        }
        area_split_exit(C, op);
-
+       
        return OPERATOR_CANCELLED;
 }
 
@@ -1221,7 +1266,7 @@ static int area_split_modal(bContext *C, wmOperator *op, wmEvent *event)
        sAreaSplitData *sd= (sAreaSplitData *)op->customdata;
        float fac;
        int dir;
-
+       
        /* execute the events */
        switch(event->type) {
                case MOUSEMOVE:
@@ -1232,8 +1277,6 @@ static int area_split_modal(bContext *C, wmOperator *op, wmEvent *event)
                        
                        fac= (dir == 'v') ? event->x-sd->origmin : event->y-sd->origmin;
                        RNA_float_set(op->ptr, "factor", fac / (float)sd->origsize);
-                       
-                       WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
                        break;
                        
                case LEFTMOUSE:
@@ -1251,9 +1294,9 @@ static int area_split_modal(bContext *C, wmOperator *op, wmEvent *event)
 }
 
 static EnumPropertyItem prop_direction_items[] = {
-       {'h', "HORIZONTAL", 0, "Horizontal", ""},
-       {'v', "VERTICAL", 0, "Vertical", ""},
-       {0, NULL, 0, NULL, NULL}};
+{'h', "HORIZONTAL", 0, "Horizontal", ""},
+{'v', "VERTICAL", 0, "Vertical", ""},
+{0, NULL, 0, NULL, NULL}};
 
 static void SCREEN_OT_area_split(wmOperatorType *ot)
 {
@@ -1283,17 +1326,55 @@ typedef struct RegionMoveData {
        ScrArea *sa;
        int bigger, smaller, origval;
        int origx, origy;
+       int maxsize;
        char edge;
        
 } RegionMoveData;
 
+
+static int area_max_regionsize(ScrArea *sa, ARegion *scalear, char edge)
+{
+       ARegion *ar;
+       int dist;
+       
+       if(edge=='l' || edge=='r') {
+               dist = sa->totrct.xmax - sa->totrct.xmin;
+       } else {        /* t, b */
+               dist = sa->totrct.ymax - sa->totrct.ymin;
+       }
+       
+       /* subtractwidth of regions on opposite side 
+        * prevents dragging regions into other opposite regions */
+       for (ar=sa->regionbase.first; ar; ar=ar->next)
+       {
+               if (scalear->alignment == RGN_ALIGN_TOP && ar->alignment == RGN_ALIGN_BOTTOM)
+                       dist -= ar->winy;
+               else if (scalear->alignment == RGN_ALIGN_BOTTOM && ar->alignment == RGN_ALIGN_TOP)
+                       dist -= ar->winy;
+               else if (scalear->alignment == RGN_ALIGN_LEFT && ar->alignment == RGN_ALIGN_RIGHT)
+                       dist -= ar->winx;
+               else if (scalear->alignment == RGN_ALIGN_RIGHT && ar->alignment == RGN_ALIGN_LEFT)
+                       dist -= ar->winx;
+       }
+       
+       return dist;
+}
+
 static int region_scale_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
        sActionzoneData *sad= event->customdata;
-       AZone *az= sad->az;
+       AZone *az;
+       
+       if(event->type!=EVT_ACTIONZONE_REGION) {
+               BKE_report(op->reports, RPT_ERROR, "Can only scale region size from an action zone");   
+               return OPERATOR_CANCELLED;
+       }
+       
+       az = sad->az;
        
        if(az->ar) {
                RegionMoveData *rmd= MEM_callocN(sizeof(RegionMoveData), "RegionMoveData");
+               int maxsize;
                
                op->customdata= rmd;
                
@@ -1303,10 +1384,28 @@ static int region_scale_invoke(bContext *C, wmOperator *op, wmEvent *event)
                rmd->edge= az->edge;
                rmd->origx= event->x;
                rmd->origy= event->y;
-               if(rmd->edge=='l' || rmd->edge=='r') 
-                       rmd->origval= rmd->ar->type->minsizex;
+               rmd->maxsize = area_max_regionsize(rmd->sa, rmd->ar, rmd->edge);
+               
+               /* if not set we do now, otherwise it uses type */
+               if(rmd->ar->sizex==0) 
+                       rmd->ar->sizex= rmd->ar->type->prefsizex;
+               if(rmd->ar->sizey==0) 
+                       rmd->ar->sizey= rmd->ar->type->prefsizey;
+               
+               /* now copy to regionmovedata */
+               if(rmd->edge=='l' || rmd->edge=='r') {
+                       rmd->origval= rmd->ar->sizex;
+               } else {
+                       rmd->origval= rmd->ar->sizey;
+               }
+               
+               /* limit headers to standard height for now */
+               if (rmd->ar->regiontype == RGN_TYPE_HEADER)
+                       maxsize = rmd->ar->type->prefsizey;
                else
-                       rmd->origval= rmd->ar->type->minsizey;
+                       maxsize = 1000;
+               
+               CLAMP(rmd->maxsize, 0, maxsize);
                
                /* add temp handler */
                WM_event_add_modal_handler(C, op);
@@ -1329,10 +1428,12 @@ static int region_scale_modal(bContext *C, wmOperator *op, wmEvent *event)
                        if(rmd->edge=='l' || rmd->edge=='r') {
                                delta= event->x - rmd->origx;
                                if(rmd->edge=='l') delta= -delta;
-                               rmd->ar->type->minsizex= rmd->origval + delta;
-                               CLAMP(rmd->ar->type->minsizex, 0, 1000);
-                               if(rmd->ar->type->minsizex < 24) {
-                                       rmd->ar->type->minsizex= rmd->origval;
+                               
+                               rmd->ar->sizex= rmd->origval + delta;
+                               CLAMP(rmd->ar->sizex, 0, rmd->maxsize);
+                               
+                               if(rmd->ar->sizex < 24) {
+                                       rmd->ar->sizex= rmd->origval;
                                        if(!(rmd->ar->flag & RGN_FLAG_HIDDEN))
                                                ED_region_toggle_hidden(C, rmd->ar);
                                }
@@ -1342,19 +1443,23 @@ static int region_scale_modal(bContext *C, wmOperator *op, wmEvent *event)
                        else {
                                delta= event->y - rmd->origy;
                                if(rmd->edge=='b') delta= -delta;
-                               rmd->ar->type->minsizey= rmd->origval + delta;
-                               CLAMP(rmd->ar->type->minsizey, 0, 1000);
-                               if(rmd->ar->type->minsizey < 24) {
-                                       rmd->ar->type->minsizey= rmd->origval;
+                               
+                               rmd->ar->sizey= rmd->origval + delta;
+                               CLAMP(rmd->ar->sizey, 0, rmd->maxsize);
+                               
+                               if(rmd->ar->sizey < 24) {
+                                       rmd->ar->sizey= rmd->origval;
                                        if(!(rmd->ar->flag & RGN_FLAG_HIDDEN))
                                                ED_region_toggle_hidden(C, rmd->ar);
                                }
                                else if(rmd->ar->flag & RGN_FLAG_HIDDEN)
                                        ED_region_toggle_hidden(C, rmd->ar);
                        }
-                       
+#ifdef WM_FAST_DRAW
+                       ED_area_tag_redraw(rmd->sa);
+#endif
                        WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
-                                       
+                       
                        break;
                        
                case LEFTMOUSE:
@@ -1363,12 +1468,15 @@ static int region_scale_modal(bContext *C, wmOperator *op, wmEvent *event)
                                if(ABS(event->x - rmd->origx) < 2 && ABS(event->y - rmd->origy) < 2) {
                                        if(rmd->ar->flag & RGN_FLAG_HIDDEN) {
                                                ED_region_toggle_hidden(C, rmd->ar);
+#ifdef WM_FAST_DRAW
+                                               ED_area_tag_redraw(rmd->sa);
+#endif
                                                WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
                                        }
                                }
                                MEM_freeN(op->customdata);
                                op->customdata = NULL;
-
+                               
                                return OPERATOR_FINISHED;
                        }
                        break;
@@ -1403,13 +1511,13 @@ static void SCREEN_OT_region_scale(wmOperatorType *ot)
 static int frame_offset_exec(bContext *C, wmOperator *op)
 {
        int delta;
-
+       
        delta = RNA_int_get(op->ptr, "delta");
-
+       
        CTX_data_scene(C)->r.cfra += delta;
-
+       
        WM_event_add_notifier(C, NC_SCENE|ND_FRAME, CTX_data_scene(C));
-
+       
        return OPERATOR_FINISHED;
 }
 
@@ -1417,12 +1525,12 @@ static void SCREEN_OT_frame_offset(wmOperatorType *ot)
 {
        ot->name = "Frame Offset";
        ot->idname = "SCREEN_OT_frame_offset";
-
+       
        ot->exec= frame_offset_exec;
-
+       
        ot->poll= ED_operator_screenactive;
        ot->flag= 0;
-
+       
        /* rna */
        RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
 }
@@ -1437,9 +1545,9 @@ static int frame_jump_exec(bContext *C, wmOperator *op)
                CFRA= PEFRA;
        else
                CFRA= PSFRA;
-
+       
        WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
-
+       
        return OPERATOR_FINISHED;
 }
 
@@ -1448,12 +1556,12 @@ static void SCREEN_OT_frame_jump(wmOperatorType *ot)
        ot->name = "Jump to Endpoint";
        ot->description= "Jump to first/last frame in frame range.";
        ot->idname = "SCREEN_OT_frame_jump";
-
+       
        ot->exec= frame_jump_exec;
-
+       
        ot->poll= ED_operator_screenactive;
        ot->flag= 0;
-
+       
        /* rna */
        RNA_def_boolean(ot->srna, "end", 0, "Last Frame", "Jump to the last frame of the frame range.");
 }
@@ -1483,7 +1591,7 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op)
                scene_to_keylist(NULL, scene, &keys, NULL);
        if (ob && ob->adt)
                ob_to_keylist(NULL, ob, &keys, NULL);
-               
+       
        /* build linked-list for searching */
        BLI_dlrbTree_linkedlist_sync(&keys);
        
@@ -1497,13 +1605,13 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op)
        if (ak) 
                CFRA= (int)ak->cfra;
        else
-               BKE_report(op->reports, RPT_ERROR, "No more keyframes to jump to in this direction");
+               BKE_report(op->reports, RPT_INFO, "No more keyframes to jump to in this direction");
        
        /* free temp stuff */
        BLI_dlrbTree_free(&keys);
        
        WM_event_add_notifier(C, NC_SCENE|ND_FRAME, CTX_data_scene(C));
-
+       
        return OPERATOR_FINISHED;
 }
 
@@ -1512,12 +1620,12 @@ static void SCREEN_OT_keyframe_jump(wmOperatorType *ot)
        ot->name = "Jump to Keyframe";
        ot->description= "Jump to previous/next keyframe.";
        ot->idname = "SCREEN_OT_keyframe_jump";
-
+       
        ot->exec= keyframe_jump_exec;
-
+       
        ot->poll= ED_operator_screenactive;
        ot->flag= 0;
-
+       
        /* rna */
        RNA_def_boolean(ot->srna, "next", 1, "Next Keyframe", "");
 }
@@ -1533,9 +1641,9 @@ static int screen_set_exec(bContext *C, wmOperator *op)
        int tot= BLI_countlist(&CTX_data_main(C)->screen);
        int delta= RNA_int_get(op->ptr, "delta");
        
-       /* this screen is 'fake', solve later XXX */
+       /* return to previous state before switching screens */
        if(sa && sa->full)
-               return OPERATOR_CANCELLED;
+               ED_screen_full_restore(C, sa);
        
        if(delta==1) {
                while(tot--) {
@@ -1596,7 +1704,7 @@ static void SCREEN_OT_screen_full_area(wmOperatorType *ot)
        ot->exec= screen_full_area_exec;
        ot->poll= ED_operator_areaactive;
        ot->flag= 0;
-
+       
 }
 
 
@@ -1604,40 +1712,40 @@ static void SCREEN_OT_screen_full_area(wmOperatorType *ot)
 /* ************** join area operator ********************************************** */
 
 /* operator state vars used:  
                      x1, y1     mouse coord in first area, which will disappear
                      x2, y2     mouse coord in 2nd area, which will become joined
-
-functions:
-
  init()   find edge based on state vars 
                      test if the edge divides two areas, 
                      store active and nonactive area,
-            
  apply()  do the actual join
-
  exit()      cleanup, send notifier
-
-callbacks:
-
  exec()      calls init, apply, exit 
-   
  invoke() sets mouse coords in x,y
           call init()
           add modal handler
-
  modal()     accept modal events while doing it
                      call apply() with active window and nonactive window
           call exit() and remove handler when LMB confirm
-
-*/
+ x1, y1     mouse coord in first area, which will disappear
+ x2, y2     mouse coord in 2nd area, which will become joined
+ functions:
+ init()   find edge based on state vars 
+ test if the edge divides two areas, 
+ store active and nonactive area,
+ apply()  do the actual join
exit()        cleanup, send notifier
+ callbacks:
exec()        calls init, apply, exit 
+ invoke() sets mouse coords in x,y
+ call init()
+ add modal handler
modal()       accept modal events while doing it
+ call apply() with active window and nonactive window
+ call exit() and remove handler when LMB confirm
+ */
 
 typedef struct sAreaJoinData
-{
-       ScrArea *sa1;   /* first area to be considered */
-       ScrArea *sa2;   /* second area to be considered */
-       ScrArea *scr;   /* designed for removal */
-
-} sAreaJoinData;
+       {
+               ScrArea *sa1;   /* first area to be considered */
+               ScrArea *sa2;   /* second area to be considered */
+               ScrArea *scr;   /* designed for removal */
+               
+       } sAreaJoinData;
 
 
 /* validate selection inside screen, set variables OK */
@@ -1649,7 +1757,7 @@ static int area_join_init(bContext *C, wmOperator *op)
        sAreaJoinData* jd= NULL;
        int x1, y1;
        int x2, y2;
-
+       
        /* required properties, make negative to get return 0 if not set by caller */
        x1= RNA_int_get(op->ptr, "x1");
        y1= RNA_int_get(op->ptr, "y1");
@@ -1660,9 +1768,9 @@ static int area_join_init(bContext *C, wmOperator *op)
        sa2 = screen_areahascursor(CTX_wm_screen(C), x2, y2);
        if(sa1==NULL || sa2==NULL || sa1==sa2)
                return 0;
-
+       
        jd = (sAreaJoinData*)MEM_callocN(sizeof (sAreaJoinData), "op_area_join");
-               
+       
        jd->sa1 = sa1;
        jd->sa1->flag |= AREA_FLAG_DRAWJOINFROM;
        jd->sa2 = sa2;
@@ -1678,7 +1786,7 @@ static int area_join_apply(bContext *C, wmOperator *op)
 {
        sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
        if (!jd) return 0;
-
+       
        if(!screen_area_join(C, CTX_wm_screen(C), jd->sa1, jd->sa2)){
                return 0;
        }
@@ -1686,7 +1794,7 @@ static int area_join_apply(bContext *C, wmOperator *op)
                CTX_wm_area_set(C, NULL);
                CTX_wm_region_set(C, NULL);
        }
-
+       
        return 1;
 }
 
@@ -1697,7 +1805,7 @@ static void area_join_exit(bContext *C, wmOperator *op)
                MEM_freeN(op->customdata);
                op->customdata = NULL;
        }
-
+       
        /* this makes sure aligned edges will result in aligned grabbing */
        removedouble_scredges(CTX_wm_screen(C));
        removenotused_scredges(CTX_wm_screen(C));
@@ -1711,17 +1819,17 @@ static int area_join_exec(bContext *C, wmOperator *op)
        
        area_join_apply(C, op);
        area_join_exit(C, op);
-
+       
        return OPERATOR_FINISHED;
 }
 
 /* interaction callback */
 static int area_join_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
-
+       
        if(event->type==EVT_ACTIONZONE_AREA) {
                sActionzoneData *sad= event->customdata;
-
+               
                if(sad->modifier>0) {
                        return OPERATOR_PASS_THROUGH;
                }
@@ -1739,13 +1847,13 @@ static int area_join_invoke(bContext *C, wmOperator *op, wmEvent *event)
                RNA_int_set(op->ptr, "y1", sad->y);
                RNA_int_set(op->ptr, "x2", event->x);
                RNA_int_set(op->ptr, "y2", event->y);
-
+               
                if(!area_join_init(C, op)) 
                        return OPERATOR_PASS_THROUGH;
-       
+               
                /* add temp handler */
                WM_event_add_modal_handler(C, op);
-       
+               
                return OPERATOR_RUNNING_MODAL;
        }
        
@@ -1755,7 +1863,7 @@ static int area_join_invoke(bContext *C, wmOperator *op, wmEvent *event)
 static int area_join_cancel(bContext *C, wmOperator *op)
 {
        sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
-
+       
        if (jd->sa1) {
                jd->sa1->flag &= ~AREA_FLAG_DRAWJOINFROM;
                jd->sa1->flag &= ~AREA_FLAG_DRAWJOINTO;
@@ -1764,11 +1872,11 @@ static int area_join_cancel(bContext *C, wmOperator *op)
                jd->sa2->flag &= ~AREA_FLAG_DRAWJOINFROM;
                jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
        }
-
+       
        WM_event_add_notifier(C, NC_WINDOW, NULL);
        
        area_join_exit(C, op);
-
+       
        return OPERATOR_CANCELLED;
 }
 
@@ -1782,69 +1890,73 @@ static int area_join_modal(bContext *C, wmOperator *op, wmEvent *event)
        switch(event->type) {
                        
                case MOUSEMOVE: 
-                       {
-                               ScrArea *sa = screen_areahascursor(sc, event->x, event->y);
-                               int dir;
-                               
-                               if (sa) {                                       
-                                       if (jd->sa1 != sa) {
-                                               dir = area_getorientation(sc, jd->sa1, sa);
-                                               if (dir >= 0) {
-                                                       if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
-                                                       jd->sa2 = sa;
-                                                       jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
-                                               } 
-                                               else {
-                                                       /* we are not bordering on the previously selected area 
-                                                          we check if area has common border with the one marked for removal
-                                                          in this case we can swap areas.
-                                                       */
-                                                       dir = area_getorientation(sc, sa, jd->sa2);
-                                                       if (dir >= 0) {
-                                                               if (jd->sa1) jd->sa1->flag &= ~AREA_FLAG_DRAWJOINFROM;
-                                                               if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
-                                                               jd->sa1 = jd->sa2;
-                                                               jd->sa2 = sa;
-                                                               if (jd->sa1) jd->sa1->flag |= AREA_FLAG_DRAWJOINFROM;
-                                                               if (jd->sa2) jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
-                                                       } 
-                                                       else {
-                                                               if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
-                                                               jd->sa2 = NULL;
-                                                       }
-                                               }
-                                               WM_event_add_notifier(C, NC_WINDOW, NULL);
+               {
+                       ScrArea *sa = screen_areahascursor(sc, event->x, event->y);
+                       int dir;
+                       
+                       if (sa) {                                       
+                               if (jd->sa1 != sa) {
+                                       dir = area_getorientation(sc, jd->sa1, sa);
+                                       if (dir >= 0) {
+                                               if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
+                                               jd->sa2 = sa;
+                                               jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
                                        } 
                                        else {
-                                               /* we are back in the area previously selected for keeping 
-                                                * we swap the areas if possible to allow user to choose */
-                                               if (jd->sa2 != NULL) {
+                                               /* we are not bordering on the previously selected area 
+                                                we check if area has common border with the one marked for removal
+                                                in this case we can swap areas.
+                                                */
+                                               dir = area_getorientation(sc, sa, jd->sa2);
+                                               if (dir >= 0) {
                                                        if (jd->sa1) jd->sa1->flag &= ~AREA_FLAG_DRAWJOINFROM;
                                                        if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
                                                        jd->sa1 = jd->sa2;
                                                        jd->sa2 = sa;
                                                        if (jd->sa1) jd->sa1->flag |= AREA_FLAG_DRAWJOINFROM;
                                                        if (jd->sa2) jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
-                                                       dir = area_getorientation(sc, jd->sa1, jd->sa2);
-                                                       if (dir < 0) {
-                                                               printf("oops, didn't expect that!\n");
-                                                       }
                                                } 
                                                else {
-                                                       dir = area_getorientation(sc, jd->sa1, sa);
-                                                       if (dir >= 0) {
-                                                               if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
-                                                               jd->sa2 = sa;
-                                                               jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
-                                                       }
+                                                       if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
+                                                       jd->sa2 = NULL;
                                                }
-                                               WM_event_add_notifier(C, NC_WINDOW, NULL);
                                        }
+                                       WM_event_add_notifier(C, NC_WINDOW, NULL);
+                               } 
+                               else {
+                                       /* we are back in the area previously selected for keeping 
+                                        * we swap the areas if possible to allow user to choose */
+                                       if (jd->sa2 != NULL) {
+                                               if (jd->sa1) jd->sa1->flag &= ~AREA_FLAG_DRAWJOINFROM;
+                                               if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
+                                               jd->sa1 = jd->sa2;
+                                               jd->sa2 = sa;
+                                               if (jd->sa1) jd->sa1->flag |= AREA_FLAG_DRAWJOINFROM;
+                                               if (jd->sa2) jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
+                                               dir = area_getorientation(sc, jd->sa1, jd->sa2);
+                                               if (dir < 0) {
+                                                       printf("oops, didn't expect that!\n");
+                                               }
+                                       } 
+                                       else {
+                                               dir = area_getorientation(sc, jd->sa1, sa);
+                                               if (dir >= 0) {
+                                                       if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
+                                                       jd->sa2 = sa;
+                                                       jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
+                                               }
+                                       }
+                                       WM_event_add_notifier(C, NC_WINDOW, NULL);
                                }
                        }
+               }
                        break;
                case LEFTMOUSE:
                        if(event->val==KM_RELEASE) {
+#ifdef WM_FAST_DRAW
+                               ED_area_tag_redraw(jd->sa1);
+                               ED_area_tag_redraw(jd->sa2);
+#endif
                                area_join_apply(C, op);
                                WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
                                area_join_exit(C, op);
@@ -1852,10 +1964,11 @@ static int area_join_modal(bContext *C, wmOperator *op, wmEvent *event)
                        }
                        break;
                        
+               case RIGHTMOUSE:
                case ESCKEY:
                        return area_join_cancel(C, op);
        }
-
+       
        return OPERATOR_RUNNING_MODAL;
 }
 
@@ -1872,9 +1985,9 @@ static void SCREEN_OT_area_join(wmOperatorType *ot)
        ot->invoke= area_join_invoke;
        ot->modal= area_join_modal;
        ot->poll= ED_operator_areaactive;
-
+       
        ot->flag= OPTYPE_BLOCKING;
-
+       
        /* rna */
        RNA_def_int(ot->srna, "x1", -100, INT_MIN, INT_MAX, "X 1", "", INT_MIN, INT_MAX);
        RNA_def_int(ot->srna, "y1", -100, INT_MIN, INT_MAX, "Y 1", "", INT_MIN, INT_MAX);
@@ -1922,10 +2035,10 @@ static int repeat_history_invoke(bContext *C, wmOperator *op, wmEvent *event)
        
        pup= uiPupMenuBegin(C, op->type->name, 0);
        layout= uiPupMenuLayout(pup);
-
+       
        for (i=items-1, lastop= wm->operators.last; lastop; lastop= lastop->prev, i--)
                uiItemIntO(layout, lastop->type->name, 0, op->type->idname, "index", i);
-
+       
        uiPupMenuEnd(C, pup);
        
        return OPERATOR_CANCELLED;
@@ -1943,7 +2056,7 @@ static int repeat_history_exec(bContext *C, wmOperator *op)
                
                WM_operator_repeat(C, op);
        }
-                                        
+       
        return OPERATOR_FINISHED;
 }
 
@@ -1969,7 +2082,7 @@ static int redo_last_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
        wmWindowManager *wm= CTX_wm_manager(C);
        wmOperator *lastop;
-
+       
        /* only for operators that are registered and did an undo push */
        for(lastop= wm->operators.last; lastop; lastop= lastop->prev)
                if((lastop->type->flag & OPTYPE_REGISTER) && (lastop->type->flag & OPTYPE_UNDO))
@@ -1977,7 +2090,7 @@ static int redo_last_invoke(bContext *C, wmOperator *op, wmEvent *event)
        
        if(lastop)
                WM_operator_redo_popup(C, lastop);
-
+       
        return OPERATOR_CANCELLED;
 }
 
@@ -1997,7 +2110,7 @@ static void SCREEN_OT_redo_last(wmOperatorType *ot)
 /* ************** region four-split operator ***************************** */
 
 /* insert a region in the area region list */
-static int region_foursplit_exec(bContext *C, wmOperator *op)
+static int region_quadview_exec(bContext *C, wmOperator *op)
 {
        ARegion *ar= CTX_wm_region(C);
        
@@ -2026,6 +2139,9 @@ static int region_foursplit_exec(bContext *C, wmOperator *op)
                                MEM_freeN(ar);
                        }
                }
+#ifdef WM_FAST_DRAW
+               ED_area_tag_redraw(sa);
+#endif
                WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
        }
        else if(ar->next)
@@ -2062,6 +2178,9 @@ static int region_foursplit_exec(bContext *C, wmOperator *op)
                        rv3d->view= RV3D_VIEW_CAMERA; rv3d->persp= RV3D_CAMOB;
                }
                
+#ifdef WM_FAST_DRAW
+               ED_area_tag_redraw(sa);
+#endif
                WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
        }
        
@@ -2069,16 +2188,16 @@ static int region_foursplit_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-static void SCREEN_OT_region_foursplit(wmOperatorType *ot)
+static void SCREEN_OT_region_quadview(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Toggle Quad View";
        ot->description= "Split selected area into camera, front, right & top views.";
-       ot->idname= "SCREEN_OT_region_foursplit";
+       ot->idname= "SCREEN_OT_region_quadview";
        
        /* api callbacks */
-//     ot->invoke= WM_operator_confirm;
-       ot->exec= region_foursplit_exec;
+       //      ot->invoke= WM_operator_confirm;
+       ot->exec= region_quadview_exec;
        ot->poll= ED_operator_areaactive;
        ot->flag= 0;
 }
@@ -2091,7 +2210,10 @@ static void SCREEN_OT_region_foursplit(wmOperatorType *ot)
 static int region_flip_exec(bContext *C, wmOperator *op)
 {
        ARegion *ar= CTX_wm_region(C);
-
+       
+       if (!ar)
+               return OPERATOR_CANCELLED;
+       
        if(ar->alignment==RGN_ALIGN_TOP)
                ar->alignment= RGN_ALIGN_BOTTOM;
        else if(ar->alignment==RGN_ALIGN_BOTTOM)
@@ -2101,8 +2223,10 @@ static int region_flip_exec(bContext *C, wmOperator *op)
        else if(ar->alignment==RGN_ALIGN_RIGHT)
                ar->alignment= RGN_ALIGN_LEFT;
        
+#ifdef WM_FAST_DRAW
+               ED_area_tag_redraw(CTX_wm_area(C));
+#endif
        WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
-       printf("executed region flip\n");
        
        return OPERATOR_FINISHED;
 }
@@ -2155,8 +2279,11 @@ static int header_flip_exec(bContext *C, wmOperator *op)
        else if(ar->alignment==RGN_ALIGN_RIGHT)
                ar->alignment= RGN_ALIGN_LEFT;
        
+#ifdef WM_FAST_DRAW
+       ED_area_tag_redraw(CTX_wm_area(C));
+#endif
+
        WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
-       printf("executed header region flip\n");
        
        return OPERATOR_FINISHED;
 }
@@ -2183,7 +2310,7 @@ static int header_toolbox_invoke(bContext *C, wmOperator *op, wmEvent *event)
        ARegion *ar= CTX_wm_region(C);
        uiPopupMenu *pup;
        uiLayout *layout;
-
+       
        pup= uiPupMenuBegin(C, "Header", 0);
        layout= uiPupMenuLayout(pup);
        
@@ -2198,13 +2325,13 @@ static int header_toolbox_invoke(bContext *C, wmOperator *op, wmEvent *event)
        /* file browser should be fullscreen all the time, but other regions can be maximised/restored... */
        if (sa->spacetype != SPACE_FILE) {
                if (sa->full) 
-                       uiItemO(layout, "Tile Window", 0, "SCREEN_OT_screen_full_area");
+                       uiItemO(layout, "Tile Area", 0, "SCREEN_OT_screen_full_area");
                else
-                       uiItemO(layout, "Maximize Window", 0, "SCREEN_OT_screen_full_area");
+                       uiItemO(layout, "Maximize Area", 0, "SCREEN_OT_screen_full_area");
        }
        
        uiPupMenuEnd(C, pup);
-
+       
        return OPERATOR_CANCELLED;
 }
 
@@ -2224,7 +2351,7 @@ void SCREEN_OT_header_toolbox(wmOperatorType *ot)
 static int match_region_with_redraws(int spacetype, int regiontype, int redraws)
 {
        if(regiontype==RGN_TYPE_WINDOW) {
-
+               
                switch (spacetype) {
                        case SPACE_VIEW3D:
                                if(redraws & TIME_ALL_3D_WIN)
@@ -2268,6 +2395,14 @@ static int match_region_with_redraws(int spacetype, int regiontype, int redraws)
                if(spacetype==SPACE_TIME)
                        return 1;
        }
+       else if (regiontype==RGN_TYPE_PREVIEW) {
+               switch (spacetype) {
+                       case SPACE_SEQ:
+                               if(redraws & (TIME_SEQ|TIME_ALL_ANIM_WIN))
+                                       return 1;
+                               break;
+               }
+       }
        return 0;
 }
 
@@ -2309,7 +2444,7 @@ static int screen_animation_step(bContext *C, wmOperator *op, wmEvent *event)
                
                if (sad->flag & ANIMPLAY_FLAG_REVERSE) {
                        /* jump back to end? */
-                       if (scene->r.psfra) {
+                       if (PRVRANGEON) {
                                if (scene->r.cfra < scene->r.psfra) {
                                        scene->r.cfra= scene->r.pefra;
                                        sad->flag |= ANIMPLAY_FLAG_JUMPED;
@@ -2324,7 +2459,7 @@ static int screen_animation_step(bContext *C, wmOperator *op, wmEvent *event)
                }
                else {
                        /* jump back to start? */
-                       if (scene->r.psfra) {
+                       if (PRVRANGEON) {
                                if (scene->r.cfra > scene->r.pefra) {
                                        scene->r.cfra= scene->r.psfra;
                                        sad->flag |= ANIMPLAY_FLAG_JUMPED;
@@ -2339,10 +2474,11 @@ static int screen_animation_step(bContext *C, wmOperator *op, wmEvent *event)
                }
                
                /* since we follow drawflags, we can't send notifier but tag regions ourselves */
+
                ED_update_for_newframe(C, 1);
                
                sound_update_playing(C);
-               
+
                for(sa= screen->areabase.first; sa; sa= sa->next) {
                        ARegion *ar;
                        for(ar= sa->regionbase.first; ar; ar= ar->next) {
@@ -2395,7 +2531,7 @@ static int screen_animation_play(bContext *C, wmOperator *op, wmEvent *event)
                ScrArea *sa= CTX_wm_area(C);
                int mode= (RNA_boolean_get(op->ptr, "reverse")) ? -1 : 1;
                int sync= -1;
-
+               
                if(RNA_property_is_set(op->ptr, "sync"))
                        sync= (RNA_boolean_get(op->ptr, "sync"));
                
@@ -2406,16 +2542,16 @@ static int screen_animation_play(bContext *C, wmOperator *op, wmEvent *event)
                        ED_screen_animation_timer(C, stime->redraws, sync, mode);
                        
                        /* update region if TIME_REGION was set, to leftmost 3d window */
-                       ED_screen_animation_timer_update(C, stime->redraws);
+                       ED_screen_animation_timer_update(screen, stime->redraws);
                }
                else {
                        int redraws = TIME_REGION|TIME_ALL_3D_WIN;
-
+                       
                        /* XXX - would like a better way to deal with this situation - Campbell */
                        if((sa) && (sa->spacetype == SPACE_SEQ)) {
                                redraws |= TIME_SEQ;
                        }
-
+                       
                        ED_screen_animation_timer(C, redraws, sync, mode);
                        
                        if(screen->animtimer) {
@@ -2483,23 +2619,23 @@ static void SCREEN_OT_animation_cancel(wmOperatorType *ot)
 /* ************** border select operator (template) ***************************** */
 
 /* operator state vars used: (added by default WM callbacks)   
      xmin, ymin     
      xmax, ymax     
-
      customdata: the wmGesture pointer
-
-callbacks:
-
      exec()  has to be filled in by user
-
      invoke() default WM function
                       adds modal handler
-
      modal() default WM function 
                      accept modal events while doing it, calls exec(), handles ESC and border drawing
-       
      poll()  has to be filled in by user for context
-*/
+ xmin, ymin     
+ xmax, ymax     
+ customdata: the wmGesture pointer
+ callbacks:
exec()        has to be filled in by user
+ invoke() default WM function
+ adds modal handler
modal()       default WM function 
+ accept modal events while doing it, calls exec(), handles ESC and border drawing
poll()        has to be filled in by user for context
+ */
 #if 0
 static int border_select_do(bContext *C, wmOperator *op)
 {
@@ -2534,14 +2670,14 @@ static void SCREEN_OT_border_select(wmOperatorType *ot)
        RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
        RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
        RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
-
+       
 }
 #endif
 
 /* ****************************** render invoking ***************** */
 
 /* set callbacks, exported to sequence render too. 
-Only call in foreground (UI) renders. */
+ Only call in foreground (UI) renders. */
 
 /* returns biggest area that is not uv/image editor. Note that it uses buttons */
 /* window as the last possible alternative.                                                                       */
@@ -2606,7 +2742,7 @@ static ScrArea *find_area_showing_r_result(bContext *C)
                        }
                }
        }
-
+       
        return sa;
 }
 
@@ -2653,6 +2789,7 @@ static void screen_set_image_output(bContext *C, int mx, int my)
        Scene *scene= CTX_data_scene(C);
        ScrArea *sa= NULL;
        SpaceImage *sima;
+       int area_was_image=0;
        
        if(scene->r.displaymode==R_OUTPUT_WINDOW) {
                rcti rect;
@@ -2677,6 +2814,9 @@ static void screen_set_image_output(bContext *C, int mx, int my)
                sa= CTX_wm_area(C);
        }
        else if(scene->r.displaymode==R_OUTPUT_SCREEN) {
+               if (CTX_wm_area(C)->spacetype == SPACE_IMAGE)
+                       area_was_image = 1;
+               
                /* this function returns with changed context */
                ED_screen_full_newspace(C, CTX_wm_area(C), SPACE_IMAGE);
                sa= CTX_wm_area(C);
@@ -2715,14 +2855,24 @@ static void screen_set_image_output(bContext *C, int mx, int my)
        /* get the correct image, and scale it */
        sima->image= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
        
-//     if(G.displaymode==2) { // XXX
-               if(sa->full) {
-                       sima->flag |= SI_FULLWINDOW|SI_PREVSPACE;
-                       
-//                     ed_screen_fullarea(C, win, sa);
-               }
-//     }
        
+       /* if we're rendering to full screen, set appropriate hints on image editor
+        * so it can restore properly on pressing esc */
+       if(sa->full) {
+               sima->flag |= SI_FULLWINDOW;
+               
+               /* Tell the image editor to revert to previous space in space list on close
+                * _only_ if it wasn't already an image editor when the render was invoked */
+               if (area_was_image == 0)
+                       sima->flag |= SI_PREVSPACE;
+               else {
+                       /* Leave it alone so the image editor will just go back from 
+                        * full screen to the original tiled setup */
+                       ;
+               }
+               
+       }
+
 }
 
 /* executes blocking render */
@@ -2736,16 +2886,19 @@ static int screen_render_exec(bContext *C, wmOperator *op)
        }
        RE_test_break_cb(re, NULL, (int (*)(void *)) blender_test_break);
        
+       /* inform Freestyle of the context */
+       FRS_set_context(C);
+
        if(RNA_boolean_get(op->ptr, "animation"))
-               RE_BlenderAnim(re, scene, scene->r.sfra, scene->r.efra, scene->r.frame_step);
+               RE_BlenderAnim(re, scene, scene->r.sfra, scene->r.efra, scene->r.frame_step, op->reports);
        else
-               RE_BlenderFrame(re, scene, scene->r.cfra);
+               RE_BlenderFrame(re, scene, NULL, scene->r.cfra);
        
        // no redraw needed, we leave state as we entered it
        ED_update_for_newframe(C, 1);
        
        WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, scene);
-
+       
        return OPERATOR_FINISHED;
 }
 
@@ -2753,11 +2906,13 @@ typedef struct RenderJob {
        Scene *scene;
        Render *re;
        wmWindow *win;
+       SceneRenderLayer *srl;
        int anim;
        Image *image;
        ImageUser iuser;
        short *stop;
        short *do_update;
+       ReportList *reports;
 } RenderJob;
 
 static void render_freejob(void *rjv)
@@ -2809,7 +2964,8 @@ static void make_renderinfo_string(RenderStats *rs, Scene *scene, char *str)
        
        /* very weak... but 512 characters is quite safe */
        if(spos >= str+IMA_RW_MAXTEXT)
-               printf("WARNING! renderwin text beyond limit \n");
+               if (G.f & G_DEBUG)
+                       printf("WARNING! renderwin text beyond limit \n");
        
 }
 
@@ -2825,7 +2981,7 @@ static void image_renderinfo_cb(void *rjv, RenderStats *rs)
        
        /* make jobs timer to send notifier */
        *(rj->do_update)= 1;
-
+       
 }
 
 /* called inside thread! */
@@ -2886,9 +3042,12 @@ static void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf
        }
        if(rectf==NULL) return;
        
+       if(ibuf->rect==NULL)
+               imb_addrectImBuf(ibuf);
+
        rectf+= 4*(rr->rectx*ymin + xmin);
        rectc= (char *)(ibuf->rect + ibuf->x*rymin + rxmin);
-
+       
        /* XXX make nice consistent functions for this */
        if (scene && (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)) {
                for(y1= 0; y1<ymax; y1++) {
@@ -2902,7 +3061,7 @@ static void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf
                                        srgb[0]= linearrgb_to_srgb(rf[0]);
                                        srgb[1]= linearrgb_to_srgb(rf[1]);
                                        srgb[2]= linearrgb_to_srgb(rf[2]);
-
+                                       
                                        rc[0]= FTOCHAR(srgb[0]);
                                        rc[1]= FTOCHAR(srgb[1]);
                                        rc[2]= FTOCHAR(srgb[2]);
@@ -2942,7 +3101,7 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec
        ibuf= BKE_image_acquire_ibuf(rj->image, &rj->iuser, &lock);
        if(ibuf) {
                image_buffer_rect_update(rj->scene, rr, ibuf, renrect);
-
+               
                /* make jobs timer to send notifier */
                *(rj->do_update)= 1;
        }
@@ -2956,10 +3115,15 @@ static void render_startjob(void *rjv, short *stop, short *do_update)
        rj->stop= stop;
        rj->do_update= do_update;
        
+#if defined(__APPLE__) && (PARALLEL == 1) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 2)
+       // Workaround for Apple gcc 4.2.1 omp vs background thread bug
+       pthread_setspecific (gomp_tls_key, thread_tls_data);
+#endif
+       
        if(rj->anim)
-               RE_BlenderAnim(rj->re, rj->scene, rj->scene->r.sfra, rj->scene->r.efra, rj->scene->r.frame_step);
+               RE_BlenderAnim(rj->re, rj->scene, rj->scene->r.sfra, rj->scene->r.efra, rj->scene->r.frame_step, rj->reports);
        else
-               RE_BlenderFrame(rj->re, rj->scene, rj->scene->r.cfra);
+               RE_BlenderFrame(rj->re, rj->scene, rj->srl, rj->scene->r.cfra);
 }
 
 /* called by render, check job 'stop' value or the global */
@@ -2979,7 +3143,7 @@ static int screen_render_modal(bContext *C, wmOperator *op, wmEvent *event)
 {
        /* no running blender, remove handler and pass through */
        if(0==WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C)))
-          return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
+               return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
        
        /* running render */
        switch (event->type) {
@@ -2995,6 +3159,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
        /* new render clears all callbacks */
        Scene *scene= CTX_data_scene(C);
+       SceneRenderLayer *srl=NULL;
        Render *re;
        wmJob *steve;
        RenderJob *rj;
@@ -3009,6 +3174,9 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
        
        /* handle UI stuff */
        WM_cursor_wait(1);
+       
+       /* inform Freestyle of the context */
+       FRS_set_context(C);
 
        /* flush multires changes (for sculpt) */
        multires_force_update(CTX_data_active_object(C));
@@ -3022,14 +3190,34 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
        
        /* ensure at least 1 area shows result */
        screen_set_image_output(C, event->x, event->y);
-
+       
+       /* single layer re-render */
+       if(RNA_property_is_set(op->ptr, "layer")) {
+               SceneRenderLayer *rl;
+               Scene *scn;
+               char scene_name[19], rl_name[RE_MAXNAME];
+               
+               RNA_string_get(op->ptr, "layer", rl_name);
+               RNA_string_get(op->ptr, "scene", scene_name);
+               
+               scn = (Scene *)BLI_findstring(&CTX_data_main(C)->scene, scene_name, offsetof(ID, name) + 2);
+               rl = (SceneRenderLayer *)BLI_findstring(&scene->r.layers, rl_name, offsetof(SceneRenderLayer, name));
+               
+               if (scn && rl) {
+                       scene = scn;
+                       srl = rl;
+               }
+       }
+       
        /* job custom data */
        rj= MEM_callocN(sizeof(RenderJob), "render job");
        rj->scene= scene;
        rj->win= CTX_wm_window(C);
+       rj->srl = srl;
        rj->anim= RNA_boolean_get(op->ptr, "animation");
        rj->iuser.scene= scene;
        rj->iuser.ok= 1;
+       rj->reports= op->reports;
        
        /* setup job */
        steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, WM_JOB_EXCL_RENDER|WM_JOB_PRIORITY);
@@ -3037,6 +3225,11 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
        WM_jobs_timer(steve, 0.2, NC_SCENE|ND_RENDER_RESULT, 0);
        WM_jobs_callbacks(steve, render_startjob, NULL, NULL);
        
+#if defined(__APPLE__) && (PARALLEL == 1) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 2)
+       // Workaround for Apple gcc 4.2.1 omp vs background thread bug
+       thread_tls_data = pthread_getspecific(gomp_tls_key);
+#endif
+       
        /* get a render result image, and make sure it is empty */
        ima= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
        BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
@@ -3053,14 +3246,12 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
        
        //      BKE_report in render!
        //      RE_error_cb(re, error_cb);
-
-       WM_jobs_start(CTX_wm_manager(C), steve);
        
-       G.afbreek= 0;
+       WM_jobs_start(CTX_wm_manager(C), steve);
        
        WM_cursor_wait(0);
        WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, scene);
-
+       
        /* add modal handler for ESC */
        WM_event_add_modal_handler(C, op);
        
@@ -3084,6 +3275,8 @@ static void SCREEN_OT_render(wmOperatorType *ot)
        ot->poll= ED_operator_screenactive;
        
        RNA_def_boolean(ot->srna, "animation", 0, "Animation", "");
+       RNA_def_string(ot->srna, "layer", "", RE_MAXNAME, "Render Layer", "Single render layer to re-render");
+       RNA_def_string(ot->srna, "scene", "", 19, "Scene", "Re-render single layer in this scene");
 }
 
 /* ****************************** opengl render *************************** */
@@ -3091,21 +3284,22 @@ static void SCREEN_OT_render(wmOperatorType *ot)
 typedef struct OGLRender {
        Render *re;
        Scene *scene;
-
+       
        View3D *v3d;
        RegionView3D *rv3d;
        ARegion *ar;
-
+       
        Image *ima;
        ImageUser iuser;
-
+       
        GPUOffScreen *ofs;
        int sizex, sizey;
-
+       
+       ReportList *reports;
        bMovieHandle *mh;
        int cfrao, nfra;
-
-       wmTimer *timer;
+       
+       wmTimer *timer; /* use to check if running modal or not (invoke'd or exec'd)*/
 } OGLRender;
 
 static void screen_opengl_render_apply(OGLRender *oglrender)
@@ -3120,10 +3314,10 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
        float winmat[4][4];
        int sizex= oglrender->sizex;
        int sizey= oglrender->sizey;
-
+       
        /* bind */
        GPU_offscreen_bind(oglrender->ofs);
-
+       
        /* render 3d view */
        if(rv3d->persp==RV3D_CAMOB && v3d->camera) {
                RE_GetCameraWindow(oglrender->re, v3d->camera, scene->r.cfra, winmat);
@@ -3131,19 +3325,19 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
        }
        else
                ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, NULL);
-
+       
        /* read in pixels & stamp */
        rr= RE_AcquireResultRead(oglrender->re);
        glReadPixels(0, 0, sizex, sizey, GL_RGBA, GL_FLOAT, rr->rectf);
        if((scene->r.scemode & R_STAMP_INFO) && (scene->r.stamp & R_STAMP_DRAW))
                BKE_stamp_buf(scene, (unsigned char *)rr->rect32, rr->rectf, rr->rectx, rr->recty, 3);
        RE_ReleaseResult(oglrender->re);
-
+       
        /* update byte from float buffer */
        ibuf= BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock);
        if(ibuf) image_buffer_rect_update(NULL, rr, ibuf, NULL);
        BKE_image_release_ibuf(oglrender->ima, lock);
-
+       
        /* unbind */
        GPU_offscreen_unbind(oglrender->ofs);
 }
@@ -3156,7 +3350,7 @@ static int screen_opengl_render_init(bContext *C, wmOperator *op)
        GPUOffScreen *ofs;
        OGLRender *oglrender;
        int sizex, sizey;
-
+       
        /* ensure we have a 3d view */
        if(!ED_view3d_context_activate(C))
                return 0;
@@ -3170,83 +3364,108 @@ static int screen_opengl_render_init(bContext *C, wmOperator *op)
        
        /* handle UI stuff */
        WM_cursor_wait(1);
-
+       
        /* create offscreen buffer */
        sizex= (scene->r.size*scene->r.xsch)/100;
        sizey= (scene->r.size*scene->r.ysch)/100;
-
+       
        view3d_operator_needs_opengl(C);
        ofs= GPU_offscreen_create(sizex, sizey);
-
+       
        if(!ofs) {
                BKE_report(op->reports, RPT_ERROR, "Failed to create OpenGL offscreen buffer.");
                return 0;
        }
-
+       
        /* allocate opengl render */
        oglrender= MEM_callocN(sizeof(OGLRender), "OGLRender");
        op->customdata= oglrender;
-
+       
        oglrender->ofs= ofs;
        oglrender->sizex= sizex;
        oglrender->sizey= sizey;
        oglrender->scene= scene;
-
+       
        oglrender->v3d= CTX_wm_view3d(C);
        oglrender->ar= CTX_wm_region(C);
        oglrender->rv3d= CTX_wm_region_view3d(C);
-
+       
        /* create image and image user */
        oglrender->ima= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
        BKE_image_signal(oglrender->ima, NULL, IMA_SIGNAL_FREE);
-
+       
        oglrender->iuser.scene= scene;
        oglrender->iuser.ok= 1;
-
+       
        /* create render and render result */
        oglrender->re= RE_NewRender(scene->id.name);
-       RE_InitState(oglrender->re, NULL, &scene->r, sizex, sizey, NULL);
-
+       RE_InitState(oglrender->re, NULL, &scene->r, NULL, sizex, sizey, NULL);
+       
        rr= RE_AcquireResultWrite(oglrender->re);
        if(rr->rectf==NULL)
-               rr->rectf= MEM_mallocN(sizeof(float)*4*sizex*sizex, "32 bits rects");
+               rr->rectf= MEM_mallocN(sizeof(float)*4*sizex*sizey, "32 bits rects");
        RE_ReleaseResult(oglrender->re);
-
+       
        return 1;
 }
 
 static void screen_opengl_render_end(bContext *C, OGLRender *oglrender)
 {
        Scene *scene= oglrender->scene;
-
+       
        if(oglrender->mh) {
                if(BKE_imtype_is_movie(scene->r.imtype))
                        oglrender->mh->end_movie();
        }
 
-       if(oglrender->timer) {
+       if(oglrender->timer) { /* exec will not have a timer */
                scene->r.cfra= oglrender->cfrao;
                scene_update_for_newframe(scene, scene->lay);
-
+               
                WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), oglrender->timer);
        }
-
+       
        WM_cursor_wait(0);
        WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, oglrender->scene);
-
+       
        GPU_offscreen_free(oglrender->ofs);
-
+       
        MEM_freeN(oglrender);
 }
 
 static int screen_opengl_render_cancel(bContext *C, wmOperator *op)
 {
        screen_opengl_render_end(C, op->customdata);
-
+       
        return OPERATOR_CANCELLED;
 }
 
-static int screen_opengl_render_modal(bContext *C, wmOperator *op, wmEvent *event)
+/* share between invoke and exec */
+static int screen_opengl_render_anim_initialize(bContext *C, wmOperator *op)
+{
+       /* initialize animation */
+       OGLRender *oglrender;
+       Scene *scene;
+
+       oglrender= op->customdata;
+       scene= oglrender->scene;
+
+       oglrender->reports= op->reports;
+       oglrender->mh= BKE_get_movie_handle(scene->r.imtype);
+       if(BKE_imtype_is_movie(scene->r.imtype)) {
+               if(!oglrender->mh->start_movie(scene, &scene->r, oglrender->sizex, oglrender->sizey, oglrender->reports)) {
+                       screen_opengl_render_end(C, oglrender);
+                       return 0;
+               }
+       }
+
+       oglrender->cfrao= scene->r.cfra;
+       oglrender->nfra= SFRA;
+       scene->r.cfra= SFRA;
+
+       return 1;
+}
+static int screen_opengl_render_anim_step(bContext *C, wmOperator *op)
 {
        OGLRender *oglrender= op->customdata;
        Scene *scene= oglrender->scene;
@@ -3256,20 +3475,6 @@ static int screen_opengl_render_modal(bContext *C, wmOperator *op, wmEvent *even
        unsigned int lay;
        int ok= 0;
 
-       switch(event->type) {
-               case ESCKEY:
-                       /* cancel */
-                       screen_opengl_render_end(C, op->customdata);
-                       return OPERATOR_FINISHED;
-               case TIMER:
-                       /* render frame? */
-                       if(oglrender->timer == event->customdata)
-                               break;
-               default:
-                       /* nothing to do */
-                       return OPERATOR_RUNNING_MODAL;
-       }
-
        /* go to next frame */
        while(CFRA<oglrender->nfra) {
                if(scene->lay & 0xFF000000)
@@ -3283,51 +3488,99 @@ static int screen_opengl_render_modal(bContext *C, wmOperator *op, wmEvent *even
 
        scene_update_for_newframe(scene, scene->lay);
 
+       if(oglrender->rv3d->persp==RV3D_CAMOB && oglrender->v3d->camera && oglrender->v3d->scenelock) {
+               /* since scene_update_for_newframe() is used rather
+                * then ED_update_for_newframe() the camera needs to be set */
+               Object *camera= scene_find_camera_switch(scene);
+
+               if(camera)
+                       oglrender->v3d->camera= scene->camera= camera;
+       }
+       
        /* render into offscreen buffer */
        screen_opengl_render_apply(oglrender);
        
        /* save to disk */
        ibuf= BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock);
-
+       
        if(ibuf) {
                if(BKE_imtype_is_movie(scene->r.imtype)) {
-                       oglrender->mh->append_movie(&scene->r, CFRA, (int*)ibuf->rect, oglrender->sizex, oglrender->sizey);
-                       printf("Append frame %d", scene->r.cfra);
-                       ok= 1;
+                       ok= oglrender->mh->append_movie(&scene->r, CFRA, (int*)ibuf->rect, oglrender->sizex, oglrender->sizey, oglrender->reports);
+                       if(ok) {
+                               printf("Append frame %d", scene->r.cfra);
+                               BKE_reportf(op->reports, RPT_INFO, "Appended frame: %d", scene->r.cfra);
+                       }
                }
                else {
-                       BKE_makepicstring(scene, name, scene->r.pic, scene->r.cfra, scene->r.imtype);
+                       BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype, scene->r.scemode & R_EXTENSION);
                        ok= BKE_write_ibuf(scene, ibuf, name, scene->r.imtype, scene->r.subimtype, scene->r.quality);
                        
-                       if(ok==0) printf("write error: cannot save %s\n", name);
-                       else printf("saved: %s", name);
+                       if(ok==0) {
+                               printf("Write error: cannot save %s\n", name);
+                               BKE_reportf(op->reports, RPT_ERROR, "Write error: cannot save %s", name);
+                       }
+                       else {
+                               printf("Saved: %s", name);
+                               BKE_reportf(op->reports, RPT_INFO, "Saved file: %s", name);
+                       }
                }
        }
-
+       
        BKE_image_release_ibuf(oglrender->ima, lock);
-
+       
        /* movie stats prints have no line break */
        printf("\n");
        
        /* go to next frame */
        oglrender->nfra += scene->r.frame_step;
        scene->r.cfra++;
-
-       WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, oglrender->scene);
-
+       
        /* stop at the end or on error */
        if(scene->r.cfra > EFRA || !ok) {
                screen_opengl_render_end(C, op->customdata);
-               return OPERATOR_FINISHED;
+               return 0;
        }
 
+       return 1;
+}
+
+
+static int screen_opengl_render_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+       OGLRender *oglrender= op->customdata;
+
+       int ret;
+
+       switch(event->type) {
+               case ESCKEY:
+                       /* cancel */
+                       screen_opengl_render_end(C, op->customdata);
+                       return OPERATOR_FINISHED;
+               case TIMER:
+                       /* render frame? */
+                       if(oglrender->timer == event->customdata)
+                               break;
+               default:
+                       /* nothing to do */
+                       return OPERATOR_RUNNING_MODAL;
+       }
+
+       ret= screen_opengl_render_anim_step(C, op);
+
+       WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, oglrender->scene);
+       
+       /* stop at the end or on error */
+       if(ret == 0) {
+               return OPERATOR_FINISHED;
+       }
+       
        return OPERATOR_RUNNING_MODAL;
 }
 
 static int screen_opengl_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
        int anim= RNA_boolean_get(op->ptr, "animation");
-
+       
        if(!screen_opengl_render_init(C, op))
                return OPERATOR_CANCELLED;
        
@@ -3336,34 +3589,57 @@ static int screen_opengl_render_invoke(bContext *C, wmOperator *op, wmEvent *eve
                screen_opengl_render_apply(op->customdata);
                screen_opengl_render_end(C, op->customdata);
                screen_set_image_output(C, event->x, event->y);
-
+               
                return OPERATOR_FINISHED;
        }
        else {
-               /* initialize animation */
-               OGLRender *oglrender;
-               Scene *scene;
+               OGLRender *oglrender= op->customdata;
 
-               oglrender= op->customdata;
-               scene= oglrender->scene;
-
-               oglrender->mh= BKE_get_movie_handle(scene->r.imtype);
-               if(BKE_imtype_is_movie(scene->r.imtype))
-                       oglrender->mh->start_movie(scene, &scene->r, oglrender->sizex, oglrender->sizey);
+               if(!screen_opengl_render_anim_initialize(C, op))
+                       return OPERATOR_CANCELLED;
 
-               oglrender->cfrao= scene->r.cfra;
-               oglrender->nfra= SFRA;
-               scene->r.cfra= SFRA;
+               screen_set_image_output(C, event->x, event->y);
 
                WM_event_add_modal_handler(C, op);
                oglrender->timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
 
-               screen_set_image_output(C, event->x, event->y);
-
                return OPERATOR_RUNNING_MODAL;
        }
 }
 
+/* executes blocking render */
+static int screen_opengl_render_exec(bContext *C, wmOperator *op)
+{
+       int anim= RNA_boolean_get(op->ptr, "animation");
+
+       if(!screen_opengl_render_init(C, op))
+               return OPERATOR_CANCELLED;
+
+       if(!anim) { /* same as invoke */
+               /* render image */
+               screen_opengl_render_apply(op->customdata);
+               screen_opengl_render_end(C, op->customdata);
+
+               return OPERATOR_FINISHED;
+       }
+       else {
+               int ret= 1;
+
+               if(!screen_opengl_render_anim_initialize(C, op))
+                       return OPERATOR_CANCELLED;
+
+               while(ret) {
+                       ret= screen_opengl_render_anim_step(C, op);
+               }
+       }
+
+       // no redraw needed, we leave state as we entered it
+//     ED_update_for_newframe(C, 1);
+       WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, CTX_data_scene(C));
+
+       return OPERATOR_FINISHED;
+}
+
 static void SCREEN_OT_opengl_render(wmOperatorType *ot)
 {
        /* identifiers */
@@ -3373,6 +3649,7 @@ static void SCREEN_OT_opengl_render(wmOperatorType *ot)
        
        /* api callbacks */
        ot->invoke= screen_opengl_render_invoke;
+       ot->exec= screen_opengl_render_exec; /* blocking */
        ot->modal= screen_opengl_render_modal;
        ot->cancel= screen_opengl_render_cancel;
        
@@ -3400,11 +3677,11 @@ static int render_view_cancel_exec(bContext *C, wmOperator *unused)
                
                if(sima->flag & SI_FULLWINDOW) {
                        sima->flag &= ~SI_FULLWINDOW;
-                       ED_screen_full_prevspace(C);
+                       ED_screen_full_prevspace(C, sa);
                }
                else
-                       ED_area_prevspace(C);
-
+                       ED_area_prevspace(C, sa);
+               
                return OPERATOR_FINISHED;
        }
        else if(sima->flag & SI_FULLWINDOW) {
@@ -3412,7 +3689,7 @@ static int render_view_cancel_exec(bContext *C, wmOperator *unused)
                ed_screen_fullarea(C, win, sa);
                return OPERATOR_FINISHED;
        }
-
+       
        return OPERATOR_PASS_THROUGH;
 }
 
@@ -3433,7 +3710,7 @@ static void SCREEN_OT_render_view_cancel(struct wmOperatorType *ot)
 static int render_view_show_invoke(bContext *C, wmOperator *unused, wmEvent *event)
 {
        ScrArea *sa= find_area_showing_r_result(C);
-
+       
        /* test if we have a temp screen in front */
        if(CTX_wm_window(C)->screen->full==SCREENTEMP) {
                wm_window_lower(CTX_wm_window(C));
@@ -3447,7 +3724,7 @@ static int render_view_show_invoke(bContext *C, wmOperator *unused, wmEvent *eve
                        
                        if(sima->flag & SI_FULLWINDOW) {
                                sima->flag &= ~SI_FULLWINDOW;
-                               ED_screen_full_prevspace(C);
+                               ED_screen_full_prevspace(C, sa);
                        }
                        else if(sima->next) {
                                ED_area_newspace(C, sa, sima->next->spacetype);
@@ -3474,6 +3751,40 @@ static void SCREEN_OT_render_view_show(struct wmOperatorType *ot)
        ot->poll= ED_operator_screenactive;
 }
 
+/* *********************** generic fullscreen 'back' button *************** */
+
+
+static int fullscreen_back_exec(bContext *C, wmOperator *op)
+{
+       bScreen *screen = CTX_wm_screen(C);
+       ScrArea *sa=NULL;
+       
+       /* search current screen for 'fullscreen' areas */
+       for (sa=screen->areabase.first; sa; sa=sa->next) {
+               if (sa->full) break;
+       }
+       if (!sa) {
+               BKE_report(op->reports, RPT_ERROR, "No fullscreen areas were found.");
+               return OPERATOR_CANCELLED;
+       }
+       
+       ED_screen_full_restore(C, sa);
+       
+       return OPERATOR_FINISHED;
+}
+
+static void SCREEN_OT_back_to_previous(struct wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Back to Previous Screen";
+       ot->description= "Revert back to the original screen layout, before fullscreen area overlay.";
+       ot->idname= "SCREEN_OT_back_to_previous";
+       
+       /* api callbacks */
+       ot->exec= fullscreen_back_exec;
+       ot->poll= ED_operator_screenactive;
+}
+
 /* *********** show user pref window ****** */
 
 static int userpref_show_invoke(bContext *C, wmOperator *unused, wmEvent *event)
@@ -3519,10 +3830,10 @@ static int screen_new_exec(bContext *C, wmOperator *op)
 {
        wmWindow *win= CTX_wm_window(C);
        bScreen *sc= CTX_wm_screen(C);
-
+       
        sc= ED_screen_duplicate(win, sc);
        WM_event_add_notifier(C, NC_SCREEN|ND_SCREENBROWSE, sc);
-
+       
        return OPERATOR_FINISHED;
 }
 
@@ -3535,7 +3846,7 @@ void SCREEN_OT_new(wmOperatorType *ot)
        
        /* api callbacks */
        ot->exec= screen_new_exec;
-
+       
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
@@ -3545,9 +3856,9 @@ void SCREEN_OT_new(wmOperatorType *ot)
 static int screen_delete_exec(bContext *C, wmOperator *op)
 {
        bScreen *sc= CTX_wm_screen(C);
-
+       
        WM_event_add_notifier(C, NC_SCREEN|ND_SCREENDELETE, sc);
-
+       
        return OPERATOR_FINISHED;
 }
 
@@ -3560,7 +3871,7 @@ void SCREEN_OT_delete(wmOperatorType *ot)
        
        /* api callbacks */
        ot->exec= screen_delete_exec;
-
+       
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
@@ -3572,17 +3883,17 @@ static int scene_new_exec(bContext *C, wmOperator *op)
        Scene *newscene, *scene= CTX_data_scene(C);
        Main *bmain= CTX_data_main(C);
        int type= RNA_enum_get(op->ptr, "type");
-
+       
        newscene= copy_scene(bmain, scene, type);
-
+       
        /* these can't be handled in blenkernel curently, so do them here */
        if(type == SCE_COPY_LINK_DATA)
                ED_object_single_users(newscene, 0);
        else if(type == SCE_COPY_FULL)
                ED_object_single_users(newscene, 1);
-
+       
        WM_event_add_notifier(C, NC_SCENE|ND_SCENEBROWSE, newscene);
-
+       
        return OPERATOR_FINISHED;
 }
 
@@ -3594,7 +3905,7 @@ void SCENE_OT_new(wmOperatorType *ot)
                {SCE_COPY_LINK_DATA, "LINK_OBJECT_DATA", 0, "Link Object Data", "Copy objects linked to data from the current scene."},
                {SCE_COPY_FULL, "FULL_COPY", 0, "Full Copy", "Make a full copy of the current scene."},
                {0, NULL, 0, NULL, NULL}};
-
+       
        /* identifiers */
        ot->name= "New Scene";
        ot->description= "Add new scene by type.";
@@ -3603,12 +3914,12 @@ void SCENE_OT_new(wmOperatorType *ot)
        /* api callbacks */
        ot->exec= scene_new_exec;
        ot->invoke= WM_menu_invoke;
-
+       
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
+       
        /* properties */
-       RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
+       ot->prop= RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
 }
 
 /********************* delete scene operator *********************/
@@ -3616,9 +3927,9 @@ void SCENE_OT_new(wmOperatorType *ot)
 static int scene_delete_exec(bContext *C, wmOperator *op)
 {
        Scene *scene= CTX_data_scene(C);
-
-       WM_event_add_notifier(C, NC_SCENE|ND_SCENEDELETE, scene);
-
+       
+       WM_event_add_notifier(C, NC_SCENE|NA_REMOVED, scene);
+       
        return OPERATOR_FINISHED;
 }
 
@@ -3631,7 +3942,7 @@ void SCENE_OT_delete(wmOperatorType *ot)
        
        /* api callbacks */
        ot->exec= scene_delete_exec;
-
+       
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
@@ -3653,13 +3964,14 @@ void ED_operatortypes_screen(void)
        WM_operatortype_append(SCREEN_OT_area_join);
        WM_operatortype_append(SCREEN_OT_area_dupli);
        WM_operatortype_append(SCREEN_OT_area_swap);
-       WM_operatortype_append(SCREEN_OT_region_foursplit);
+       WM_operatortype_append(SCREEN_OT_region_quadview);
        WM_operatortype_append(SCREEN_OT_region_scale);
        WM_operatortype_append(SCREEN_OT_region_flip);
        WM_operatortype_append(SCREEN_OT_header_flip);
        WM_operatortype_append(SCREEN_OT_header_toolbox);
        WM_operatortype_append(SCREEN_OT_screen_set);
        WM_operatortype_append(SCREEN_OT_screen_full_area);
+       WM_operatortype_append(SCREEN_OT_back_to_previous);
        WM_operatortype_append(SCREEN_OT_screenshot);
        WM_operatortype_append(SCREEN_OT_screencast);
        WM_operatortype_append(SCREEN_OT_userpref_show);
@@ -3678,13 +3990,13 @@ void ED_operatortypes_screen(void)
        WM_operatortype_append(SCREEN_OT_render_view_cancel);
        WM_operatortype_append(SCREEN_OT_render_view_show);
        WM_operatortype_append(SCREEN_OT_opengl_render);
-
+       
        /* new/delete */
        WM_operatortype_append(SCREEN_OT_new);
        WM_operatortype_append(SCREEN_OT_delete);
        WM_operatortype_append(SCENE_OT_new);
        WM_operatortype_append(SCENE_OT_delete);
-
+       
        /* tools shared by more space types */
        WM_operatortype_append(ED_OT_undo);
        WM_operatortype_append(ED_OT_redo);     
@@ -3708,12 +4020,12 @@ static void keymap_modal_set(wmKeyConfig *keyconf)
        WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_ANY, KM_ANY, 0, KM_MODAL_APPLY);
        WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, KM_MODAL_APPLY);
        WM_modalkeymap_add_item(keymap, PADENTER, KM_PRESS, KM_ANY, 0, KM_MODAL_APPLY);
-
+       
        WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, KM_MODAL_STEP10);
        WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, KM_MODAL_STEP10_OFF);
        
        WM_modalkeymap_assign(keymap, "SCREEN_OT_area_move");
-
+       
 }
 
 /* called in spacetypes.c */
@@ -3727,16 +4039,16 @@ void ED_keymap_screen(wmKeyConfig *keyconf)
        RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, 0, 0)->ptr, "modifier", 0);
        RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "modifier", 1);
        RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "modifier", 2);
-
+       
        /* screen tools */
        WM_keymap_verify_item(keymap, "SCREEN_OT_area_split", EVT_ACTIONZONE_AREA, 0, 0, 0);
        WM_keymap_verify_item(keymap, "SCREEN_OT_area_join", EVT_ACTIONZONE_AREA, 0, 0, 0);
        WM_keymap_verify_item(keymap, "SCREEN_OT_area_dupli", EVT_ACTIONZONE_AREA, 0, KM_SHIFT, 0);
-       WM_keymap_verify_item(keymap, "SCREEN_OT_area_swap", EVT_ACTIONZONE_AREA, 0, KM_ALT, 0);
+       WM_keymap_verify_item(keymap, "SCREEN_OT_area_swap", EVT_ACTIONZONE_AREA, 0, KM_CTRL, 0);
        WM_keymap_verify_item(keymap, "SCREEN_OT_region_scale", EVT_ACTIONZONE_REGION, 0, 0, 0);
-                       /* area move after action zones */
+       /* area move after action zones */
        WM_keymap_verify_item(keymap, "SCREEN_OT_area_move", LEFTMOUSE, KM_PRESS, 0, 0);
-
+       
        /* Header Editing ------------------------------------------------ */
        keymap= WM_keymap_find(keyconf, "Header", 0, 0);
        
@@ -3756,39 +4068,40 @@ void ED_keymap_screen(wmKeyConfig *keyconf)
        WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", SPACEKEY, KM_PRESS, KM_SHIFT, 0);
        WM_keymap_add_item(keymap, "SCREEN_OT_screenshot", F3KEY, KM_PRESS, KM_CTRL, 0);
        WM_keymap_add_item(keymap, "SCREEN_OT_screencast", F3KEY, KM_PRESS, KM_ALT, 0);
-
-        /* tests */
-       WM_keymap_add_item(keymap, "SCREEN_OT_region_foursplit", SKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
+       
+       /* tests */
+       WM_keymap_add_item(keymap, "SCREEN_OT_region_quadview", QKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
        WM_keymap_verify_item(keymap, "SCREEN_OT_repeat_history", F3KEY, KM_PRESS, 0, 0);
        WM_keymap_add_item(keymap, "SCREEN_OT_repeat_last", RKEY, KM_PRESS, KM_SHIFT, 0);
        WM_keymap_verify_item(keymap, "SCREEN_OT_region_flip", F5KEY, KM_PRESS, 0, 0);
        WM_keymap_verify_item(keymap, "SCREEN_OT_redo_last", F6KEY, KM_PRESS, 0, 0);
        WM_keymap_verify_item(keymap, "WM_OT_reload_scripts", F8KEY, KM_PRESS, 0, 0);
-
+       
        /* files */
        WM_keymap_add_item(keymap, "FILE_OT_execute", RETKEY, KM_PRESS, 0, 0);
        WM_keymap_add_item(keymap, "FILE_OT_execute", PADENTER, KM_PRESS, 0, 0);
        WM_keymap_add_item(keymap, "FILE_OT_cancel", ESCKEY, KM_PRESS, 0, 0);
        
        /* undo */
-       #ifdef __APPLE__
+#ifdef __APPLE__
        WM_keymap_add_item(keymap, "ED_OT_undo", ZKEY, KM_PRESS, KM_OSKEY, 0);
        WM_keymap_add_item(keymap, "ED_OT_redo", ZKEY, KM_PRESS, KM_SHIFT|KM_OSKEY, 0);
-       #endif
+#endif
        WM_keymap_add_item(keymap, "ED_OT_undo", ZKEY, KM_PRESS, KM_CTRL, 0);
        WM_keymap_add_item(keymap, "ED_OT_redo", ZKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0);
        
-                                                 
+       
        /* render */
        WM_keymap_add_item(keymap, "SCREEN_OT_render", F12KEY, KM_PRESS, 0, 0);
        RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_render", F12KEY, KM_PRESS, KM_CTRL, 0)->ptr, "animation", 1);
        WM_keymap_add_item(keymap, "SCREEN_OT_render_view_cancel", ESCKEY, KM_PRESS, 0, 0);
        WM_keymap_add_item(keymap, "SCREEN_OT_render_view_show", F11KEY, KM_PRESS, 0, 0);
+       WM_keymap_add_item(keymap, "SCREEN_OT_play_rendered_anim", F11KEY, KM_PRESS, KM_CTRL, 0);
        
        /* user prefs */
-       #ifdef __APPLE__
+#ifdef __APPLE__
        WM_keymap_add_item(keymap, "SCREEN_OT_userpref_show", COMMAKEY, KM_PRESS, KM_OSKEY, 0);
-       #endif
+#endif
        WM_keymap_add_item(keymap, "SCREEN_OT_userpref_show", UKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
        
        
@@ -3801,6 +4114,9 @@ void ED_keymap_screen(wmKeyConfig *keyconf)
        RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", LEFTARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", -1);
        RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", RIGHTARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", 1);
        
+       RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", WHEELDOWNMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "delta", 1);
+       RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", WHEELUPMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "delta", -1);
+       
        WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", DOWNARROWKEY, KM_PRESS, KM_SHIFT, 0);
        RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", RIGHTARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "end", 1);
        RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", LEFTARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "end", 0);
@@ -3813,7 +4129,7 @@ void ED_keymap_screen(wmKeyConfig *keyconf)
        WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", KKEY, KM_PRESS, 0, LKEY);
        RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", AKEY, KM_PRESS, KM_ALT|KM_SHIFT, 0)->ptr, "reverse", 1);
        WM_keymap_add_item(keymap, "SCREEN_OT_animation_cancel", ESCKEY, KM_PRESS, 0, 0);
-
+       
        keymap_modal_set(keyconf);
 }