#help_index "Windows;Task/Delay"

public U0 Refresh(I64 count = 1, Bool force = FALSE)
{//Wait for 60fps WinMgr to start & finish screen refresh.
        //0,FALSE Count Sync to WinMgr.
        //0,TRUE        Pump Messages.
        //1 Count Wait and Pump Messages.
        //2 Count Make Sure to do a Full Refresh
        //and Set Cur Pos.
        Bool     old_full_refresh, old_idle = LBts(&Fs->task_flags, TASKf_IDLE);
        CDoc    *old_doc = DocPut;
        I64              update_count;

        if (!count && force)
                LBts(&sys_semas[SEMA_JUST_PUMP_MESSAGES], 0);
        while (Bt(&sys_semas[SEMA_REFRESH_IN_PROGRESS], 0))
        {
                if (force && sys_winmgr_task)
                        sys_winmgr_task->wake_jiffy = counts.jiffies;
                Yield;
        }
        if (count > 1 && old_doc)
                old_full_refresh = LBts(&old_doc->flags, DOCf_DO_FULL_REFRESH);
        update_count = winmgr.updates+count;
        while (winmgr.updates < update_count)
        {
                if (force && sys_winmgr_task)
                        sys_winmgr_task->wake_jiffy = counts.jiffies;
                Sleep(1);
        }
        if (old_doc)
                LBEqual(&old_doc->flags, DOCf_DO_FULL_REFRESH, old_full_refresh);
        LBEqual(&Fs->task_flags, TASKf_IDLE, old_idle);
}

#help_index "Windows"

I64 WinQueueIPMessages(Bool que)
{
        static CD3I64    single_mouse = {0, 0, 0};
        F64                              time = tS;
        I64                              message_code = 0, arg1, arg2, single_arg1, single_arg2;
        CTask                   *task_focus = sys_focus_task;

        if (task_focus && !winmgr.grab_scroll)
        {
                arg1 = mouse.pos.x - task_focus->pix_left - task_focus->scroll_x;
                arg2 = mouse.pos.y - task_focus->pix_top - task_focus->scroll_y;
                single_arg1 = single_mouse.x - task_focus->pix_left - task_focus->scroll_x;
                single_arg2 = single_mouse.y - task_focus->pix_top - task_focus->scroll_y;
                if (old_mouse.presnap.x != mouse.presnap.x || old_mouse.presnap.y != mouse.presnap.y)
                {
                        if (que)
                                TaskMessage(task_focus, 0, MESSAGE_MS_MOVE, arg1, arg2, 0);
                        message_code = MESSAGE_MS_MOVE;
                }
//TODO que message for mouse.pos.z?
                if (mouse.left_dbl_time)
                {
                        if (time > mouse.left_dbl_time)
                        {
                                if (mouse.left_dbl)
                                {
                                        if (!mouse.left_down_sent)
                                        {
                                                if (que)
                                                        TaskMessage(task_focus, 0, MESSAGE_MS_L_D_DOWN, arg1, arg2, 0);
                                                mouse.left_down_sent = TRUE;
                                                message_code = MESSAGE_MS_L_D_DOWN;
                                        }
                                        if (!mouse.lb)
                                        {
                                                if (que)
                                                        TaskMessage(task_focus, 0, MESSAGE_MS_L_D_UP, arg1, arg2, 0);
                                                mouse.left_dbl_time = 0;
                                                message_code = MESSAGE_MS_L_D_UP;
                                        }
                                }
                                else
                                {
                                        if (!mouse.left_down_sent)
                                        {
                                                if (que)
                                                        TaskMessage(task_focus, 0, MESSAGE_MS_L_DOWN, single_arg1, single_arg2, 0);
                                                mouse.left_down_sent = TRUE;
                                                message_code = MESSAGE_MS_L_DOWN;
                                        }
                                        if (!mouse.lb)
                                        {
                                                if (que)
                                                        TaskMessage(task_focus, 0, MESSAGE_MS_L_UP, arg1, arg2, 0);
                                                mouse.left_dbl_time = 0;
                                                message_code = MESSAGE_MS_L_UP;
                                        }
                                }
                        }
                        else
                        {
                                if (mouse.lb && !mouse_last.lb) {
                                        mouse.left_dbl_time = time;
                                        mouse.left_dbl = TRUE;
                                }
                        }
                }
                else
                {
                        if (TaskValidate(task_focus) && Bt(&task_focus->win_inhibit, WIf_FOCUS_TASK_MS_L_D))
                        {
                                if (mouse.lb && !mouse_last.lb)
                                {
                                        if (que)
                                                TaskMessage(task_focus, 0, MESSAGE_MS_L_DOWN, arg1, arg2, 0);
                                        message_code = MESSAGE_MS_L_DOWN;
                                }
                                else if (!mouse.lb && mouse_last.lb)
                                {
                                        if (que)
                                                TaskMessage(task_focus, 0, MESSAGE_MS_L_UP, arg1, arg2, 0);
                                        message_code = MESSAGE_MS_L_UP;
                                }
                        }
                        else
                        {
                                if (mouse.lb && !mouse_last.lb)
                                {
                                        mouse.left_dbl = FALSE;
                                        mouse.left_down_sent = FALSE;
                                        mouse.left_dbl_time = time + mouse.dbl_time;
                                        single_mouse.x = mouse.pos.x;
                                        single_mouse.y = mouse.pos.y;
                                }
                        }
                }

                if (mouse.right_dbl_time)
                {
                        if (time > mouse.right_dbl_time)
                        {
                                if (mouse.right_dbl)
                                {
                                        if (!mouse.right_down_sent)
                                        {
                                                if (que)
                                                        TaskMessage(task_focus, 0, MESSAGE_MS_R_D_DOWN, arg1, arg2, 0);
                                                mouse.right_down_sent = TRUE;
                                                message_code = MESSAGE_MS_R_D_DOWN;
                                        }
                                        if (!mouse.rb)
                                        {
                                                if (que)
                                                        TaskMessage(task_focus, 0, MESSAGE_MS_R_D_UP, arg1, arg2, 0);
                                                mouse.right_dbl_time = 0;
                                                message_code = MESSAGE_MS_R_D_UP;
                                        }
                                }
                                else
                                {
                                        if (!mouse.right_down_sent)
                                        {
                                                if (que)
                                                        TaskMessage(task_focus, 0, MESSAGE_MS_R_DOWN, single_arg1, single_arg2, 0);
                                                mouse.right_down_sent = TRUE;
                                                message_code = MESSAGE_MS_R_DOWN;
                                        }
                                        if (!mouse.rb)
                                        {
                                                if (que)
                                                        TaskMessage(task_focus, 0, MESSAGE_MS_R_UP, arg1, arg2, 0);
                                                mouse.right_dbl_time = 0;
                                                message_code = MESSAGE_MS_R_UP;
                                        }
                                }
                        }
                        else
                        {
                                if (mouse.rb && !mouse_last.rb)
                                {
                                        mouse.right_dbl_time = time;
                                        mouse.right_dbl = TRUE;
                                }
                        }
                }
                else
                {
                        if (TaskValidate(task_focus) && Bt(&task_focus->win_inhibit, WIf_FOCUS_TASK_MS_R_D))
                        {
                                if (mouse.rb && !mouse_last.rb) {
                                        if (que)
                                                TaskMessage(task_focus, 0, MESSAGE_MS_R_DOWN, arg1, arg2, 0);
                                        message_code = MESSAGE_MS_R_DOWN;
                                }
                                else if (!mouse.rb && mouse_last.rb)
                                {
                                        if (que)
                                                TaskMessage(task_focus, 0, MESSAGE_MS_R_UP, arg1, arg2, 0);
                                        message_code = MESSAGE_MS_R_UP;
                                }
                        }
                        else
                        {
                                if (mouse.rb && !mouse_last.rb) {
                                        mouse.right_dbl = FALSE;
                                        mouse.right_down_sent = FALSE;
                                        mouse.right_dbl_time = time + mouse.dbl_time;
                                        single_mouse.x = mouse.pos.x;
                                        single_mouse.y = mouse.pos.y;
                                }
                        }
                }

                MemCopy(&mouse_last, &mouse, sizeof(CMouseStateGlobals));
                MemCopy(&old_mouse, &mouse, sizeof(CMouseStateGlobals));
        }

        return message_code;
}

U0 WinCalcIdles()
{
        F64                                              calc_idle_time;
        I64                                              i, k, total_jiffies, total_jiffies_delta, idle_pt_hits[MP_PROCESSORS_NUM];
        CCPU                                    *c;
        CWinMgrTimingGlobals    *t = winmgr.t;

        if ((t->calc_idle_delta_time = (calc_idle_time = tS) - t->last_calc_idle_time) > .25)
        {
                PUSHFD
                CLI
                total_jiffies = cpu_structs[0].total_jiffies;
                for (i = 0; i < mp_count; i++)
                        idle_pt_hits[i] = cpu_structs[i].idle_pt_hits;
                POPFD

                total_jiffies_delta = total_jiffies - t->last_total_jiffies;
                for (i = 0; i < mp_count; i++)
                {
                        c = &cpu_structs[i];
                        if (total_jiffies_delta && (k = idle_pt_hits[i] - t->last_idle_pt_hits[i]) >= 0)
                                c->idle_factor = Clamp(ToF64(k) / total_jiffies_delta, 0.01, 0.99);
                        else
                                c->idle_factor = 0.01;
                        t->last_idle_pt_hits[i] = idle_pt_hits[i];
                }
                t->last_total_jiffies = total_jiffies;
                t->last_calc_idle_time = calc_idle_time;
                t->calc_idle_count++;
        }
}

I64 WinMgrSleep(Bool flush_messages = FALSE)
{
        I64 timeout_val, message_code=0;
        CCtrl   *c;
        Bool     que;
        F64              t, t_delta;
        U8              *st;
        CDC             *diff;
        CDate    cdt;

        TimeCal;
        if ((t_delta = (t = tS) - winmgr.last_refresh_tS) > 0.01)
                winmgr.fps = Max(1.0 / t_delta, 1);
        else
                winmgr.fps = 99;
        winmgr.last_refresh_tS = t;
        WinCalcIdles;

        if (flush_messages)
                FifoI64Flush(kbd.scan_code_fifo);
        else if (TaskValidate(sys_focus_task))
        {
                KbdMessagesQueue;

                que = TRUE;
                if (TaskValidate(sys_focus_task) && !Bt(&sys_focus_task->win_inhibit, WIf_FOCUS_TASK_CTRLS)) {
                        c = sys_focus_task->next_ctrl;
                        while (c != &sys_focus_task->next_ctrl)
                        {
                                if (CtrlInside(c, mouse.pos.x, mouse.pos.y))
                                {
                                        que = FALSE;
                                        break;
                                }
                                c = c->next;
                        }
                }
                message_code = WinQueueIPMessages(que);
        }
        else
        {
                WinRefocus(sys_focus_task);
                if (!TaskValidate(sys_focus_task))
                        FifoI64Flush(kbd.scan_code_fifo);
        }
        if (sys_focus_task)
                LBtr(&sys_focus_task->task_flags, TASKf_HAS_SONG);
        WinMouseUpdate;

        if (!LBtr(&sys_semas[SEMA_JUST_PUMP_MESSAGES], 0))
        {
                t = tS + WINMGR_PERIOD / 8;
                while (winmgr.ideal_refresh_tS < t)
                        winmgr.ideal_refresh_tS += WINMGR_PERIOD;
                timeout_val = counts.jiffies + (winmgr.ideal_refresh_tS - tS) * JIFFY_FREQ;
                LBts(&sys_semas[SEMA_REFRESH_IN_PROGRESS], 0);
                GrUpdateScreen;
                LBtr(&sys_semas[SEMA_REFRESH_IN_PROGRESS], 0);
                if (screencast.record  && !screencast.just_audio)
                {
                        cdt = screencast.t0_now(I64) + ToI64(CDATE_FREQ * (tS - screencast.t0_tS));
                        if (!screencast.dc)
                        {
                                screencast.dc = DCCopy(screencast.dc2_alias);
                                screencast.dc->cdt = cdt;
                                st = MStrPrint(screencast.print_format, cdt);
                                GRWrite(st, screencast.dc);
                                Free(st);
                        }
                        else if (MemCompare(screencast.dc->body,
                                        screencast.dc2_alias->body, MSize(screencast.dc2_alias->body)))
                        {
                                diff = DCDiff(screencast.dc, screencast.dc2_alias);
                                diff->cdt = cdt;
                                st = MStrPrint(screencast.print_format, cdt);
                                GRWrite(st, diff);
                                Free(st);
                                DCDel(diff);
                                Free(screencast.dc->body);
                                screencast.dc->body = MAllocIdent(screencast.dc2_alias->body);
                        }
                }
                else if (screencast.dc)
                {
                        DCDel(screencast.dc); //TODO: MemRep can crash.
                        screencast.dc = NULL;
                }
                if (sys_focus_task && !Bt(&sys_focus_task->task_flags, TASKf_HAS_SONG))
                {
                        Free(music.cur_song);
                        music.cur_song = NULL;
                }
                if (music.cur_song)
                {
                        if (!music.cur_song_task)
                                music.cur_song_task = Spawn(&CurSongTask, NULL, "Song");
                }
                else if (music.cur_song_task)
                {
                        Kill(music.cur_song_task);
                        music.cur_song_task = NULL;
                }
                winmgr.updates++;
                if (mouse_hard.install_attempts) //Don't call before boot mouse install attempt
                        KbdMouseHandler(FALSE, TRUE);
                SleepUntil(timeout_val);
        }

        return message_code;
}

CDoc *WinCursorPosSet(CTask *task, I64 mouse_x, I64 mouse_y, Bool set_cursor = TRUE)
{
        CDoc *res = NULL;
        Bool  unlock;
        I64   x0, y0;

        if (!task)
                task = Fs;
        if (WinInside(mouse_x, mouse_y, task))
        {
                if ((res = DocDisplay(task)) && res->flags & DOCF_DONT_SHOW)
                        res = NULL;
                else if (set_cursor)
                {
                        unlock = DocLock(res);
                        if (res->doc_signature != DOC_SIGNATURE_VAL)
                                res = NULL;
                        else
                        {
                                x0 = res->line_start_col;
                                y0 = res->top_line_num;
                                DocRecalc(res, RECALCF_HAS_CURSOR);
                                res->x = (mouse_x-task->pix_left - task->scroll_x) / FONT_WIDTH + x0;
                                res->y = (mouse_y-task->pix_top - task->scroll_y) / FONT_HEIGHT + y0;
                                DocRecalc(res, RECALCt_FIND_CURSOR);
                                task->scroll_x = 0;
                                task->scroll_y = 0;
                                task->scroll_z = 0;
                                if (unlock)
                                        DocUnlock(res);
                        }
                }
                WinToTop(task);
        }

        return res;
}

Bool WinKeyNavMenu()
{
        I64                      i, old_key_count;
        CD3I64           old_pos, new_pos;
        CMenu           *m;
        CMenuEntry      *tmpme;
        CTask           *focus = MenuTask;

        if (Bt(kbd.down_bitmap, SC_GUI) && focus && (m = focus->cur_menu))
        {
                winmgr.show_menu = TRUE;
                sys_cur_submenu_entry = NULL;
                old_pos.x = mouse.pos.x;
                old_pos.y = mouse.pos.y;
                mouse.pos.x = new_pos.x = mouse.pos.y = new_pos.y = 0;
                while (Bt(kbd.down_bitmap, SC_GUI))
                {
                        old_key_count = kbd.count;
                        if (Bt(kbd.down_bitmap, SC_CURSOR_LEFT))
                        {
                                while (Bt(kbd.down_bitmap, SC_CURSOR_LEFT) && kbd.count == old_key_count)
                                        WinMgrSleep(TRUE);
                                if (new_pos.x)
                                {
                                        i = 0;
                                        tmpme = m->sub;
                                        while (tmpme)
                                        {
                                                if (i + MenuEntryWidth(tmpme) * FONT_WIDTH == new_pos.x)
                                                {
                                                        new_pos.x = i;
                                                        break;
                                                }
                                                i += MenuEntryWidth(tmpme) * FONT_WIDTH;
                                                tmpme = tmpme->next;
                                        }
                                }
                                new_pos.y = 0;
                        }
                        else if (Bt(kbd.down_bitmap, SC_CURSOR_RIGHT))
                        {
                                while (Bt(kbd.down_bitmap, SC_CURSOR_RIGHT) && kbd.count == old_key_count)
                                        WinMgrSleep(TRUE);
                                i = 0;
                                tmpme = m->sub;
                                while (tmpme)
                                {
                                        if (i == new_pos.x)
                                        {
                                                if (tmpme->next)
                                                        new_pos.x = i + MenuEntryWidth(tmpme) * FONT_WIDTH;
                                                break;
                                        }
                                        i += MenuEntryWidth(tmpme) * FONT_WIDTH;
                                        tmpme = tmpme->next;
                                }
                                new_pos.y = 0;
                        }
                        else if (Bt(kbd.down_bitmap, SC_CURSOR_UP))
                        {
                                while (Bt(kbd.down_bitmap, SC_CURSOR_UP) && kbd.count == old_key_count)
                                        WinMgrSleep(TRUE);
                                new_pos.y -= FONT_HEIGHT;
                        }
                        else if (Bt(kbd.down_bitmap, SC_CURSOR_DOWN))
                        {
                                while (Bt(kbd.down_bitmap, SC_CURSOR_DOWN) && kbd.count == old_key_count)
                                        WinMgrSleep(TRUE);
                                new_pos.y += FONT_HEIGHT;
                        }
                        new_pos.x = ClampI64(new_pos.x, 0, GR_WIDTH - 1);
                        new_pos.y = ClampI64(new_pos.y, 0, GR_HEIGHT - 1);
                        mouse.pos.x = new_pos.x;
                        mouse.pos.y = new_pos.y;
                        WinMgrSleep(TRUE);
                        if (!sys_cur_submenu_entry)
                                mouse.pos.y = new_pos.y=0;
                }
                if (sys_cur_submenu_entry)
                        TaskMessage(sys_focus_task, 0, sys_cur_submenu_entry->message_code,
                                                sys_cur_submenu_entry->arg1, sys_cur_submenu_entry->arg2, 0);
                winmgr.show_menu = FALSE;
                mouse.pos.x = old_pos.x;
                mouse.pos.y = old_pos.y;
                return TRUE;
        }

        return FALSE;
}

U0 WinMgrTask(I64)
{
        CTask           *task = Fs;
        CDoc            *doc;
        CDocEntry       *doc_e;
        I64                      x, y, z, message_code, my_mouse_z = 0, left, top, old_flags = RFlagsGet;
        Bool             has_border;
        CCtrl           *c;

        WinHorz(0, TEXT_COLS - 1);
        WinVert(0, TEXT_ROWS - 1);
        LBts(&Fs->display_flags, DISPLAYf_NO_BORDER);
        LBts(&Fs->display_flags, DISPLAYf_SHOW);
        gr.dc->win_task = Fs;
        Fs->win_inhibit &= ~WIF_SELF_CTRLS;
        GrSetUpTables;
        screencast.dc2_alias = DCAlias(gr.dc2);
        WinZBufUpdate;
        LBts(&sys_run_level, RLf_WINMGR);
        while (TRUE)
        {
                try
                {
wmt_start:
                        if (Bt(&sys_run_level, RLf_SYSTEM_SERVER))
                                TaskKillDying;
                        WinMgrSleep;

                        task = Fs->last_task;
                        while (TRUE)
                        {
                                CLI
                                if (!TaskValidate(task))
                                {
                                        RFlagsSet(old_flags);
                                        goto wmt_start;
                                }
                                TaskDerivedValsUpdate(task, FALSE);
                                task = task->last_task;
                                RFlagsSet(old_flags);
                                if (task == Fs)
                                        break;
                        }
                        TaskDerivedValsUpdate(Fs, FALSE);

                        task = Fs->last_task;
                        while (TRUE)
                        {
                                CLI
                                if (!TaskValidate(task))
                                {
                                        RFlagsSet(old_flags);
                                        goto wmt_start;
                                }
                                if (WinInside(mouse.pos.x, mouse.pos.y, task, FONT_WIDTH))
                                {
                                        RFlagsSet(old_flags);
                                        break;
                                }
                                if (task == Fs) { //Shouldn't happen
                                        RFlagsSet(old_flags);
                                        goto wmt_start;
                                }
                                task = task->last_task;
                                RFlagsSet(old_flags);
                        }

                        if (Bt(&task->display_flags, DISPLAYf_NO_BORDER))
                                has_border = FALSE;
                        else
                                has_border = TRUE;

                        winmgr.show_menu = FALSE;
                        sys_cur_submenu_entry = NULL;
                        if (TaskValidate(sys_focus_task) && !Bt(&sys_focus_task->win_inhibit, WIf_FOCUS_TASK_MENU))
                        {
                                if (WinKeyNavMenu)
                                        goto wmt_start;
                                if (task == Fs && 0 <= mouse.pos.y < FONT_HEIGHT && mouse_hard.installed)
                                {
                                        winmgr.show_menu = TRUE;
                                        if (mouse.lb && !old_mouse.lb)
                                        {
                                                winmgr.show_menu = TRUE;
                                                while (mouse.lb)
                                                        WinMgrSleep(TRUE);
                                                if (sys_cur_submenu_entry)
                                                        TaskMessage(sys_focus_task, 0,
                                                                                sys_cur_submenu_entry->message_code,
                                                                                sys_cur_submenu_entry->arg1,
                                                                                sys_cur_submenu_entry->arg2, 0);
                                                winmgr.show_menu = FALSE;
                                                old_mouse.lb = FALSE;
                                                goto wmt_start;
                                        }
                                }
                        }

                        //grab scroll
                        if (!Bt(&task->win_inhibit, WIf_SELF_GRAB_SCROLL) &&
                                (!TaskValidate(sys_focus_task)||
                                !Bt(&sys_focus_task->win_inhibit, WIf_FOCUS_TASK_GRAB_SCROLL)) &&
                                kbd.scan_code & SCF_CTRL && TaskValidate(task))
                        {
                                winmgr.grab_scroll_closed = FALSE;
                                winmgr.grab_scroll = TRUE;
                                while (kbd.scan_code & SCF_CTRL && TaskValidate(task) && (!ac.task ||
                                                !WinInside(mouse.pos.x, mouse.pos.y, ac.task, FONT_WIDTH)))
                                {
                                        if (mouse.lb)
                                        {
                                                winmgr.grab_scroll_closed = TRUE;
                                                x = mouse.pos.x - task->scroll_x;
                                                y = mouse.pos.y - task->scroll_y;
                                                z = mouse.pos.z - task->scroll_z;
                                                while (mouse.lb && kbd.scan_code & SCF_CTRL && TaskValidate(task))
                                                {
                                                        task->scroll_x = (mouse.pos.x - x) & ~7;
                                                        task->scroll_y = (mouse.pos.y-y) & ~7;
                                                        task->scroll_z = mouse.pos.z-z;
                                                        WinMgrSleep(TRUE);
                                                }
                                                winmgr.grab_scroll_closed = FALSE;
                                        }
                                        else if (mouse.rb)
                                        {
                                                task->scroll_x = 0;
                                                task->scroll_y = 0;
                                                task->scroll_z = 0;
                                                WinMgrSleep(TRUE);
                                        }
                                        else
                                                WinMgrSleep;
                                }
                                winmgr.grab_scroll = FALSE;
                                goto wmt_start;
                        }
                        else
                                winmgr.grab_scroll = FALSE;

                        if (!Bt(&task->win_inhibit, WIf_SELF_CTRLS) &&
                                (!TaskValidate(sys_focus_task)||
                                !Bt(&sys_focus_task->win_inhibit, WIf_FOCUS_TASK_CTRLS)))
                        {
                                if (mouse.lb && !old_mouse.lb)
                                {
                                        c = task->next_ctrl;
                                        while (c != &task->next_ctrl)
                                        {
                                                if (CtrlInside(c, mouse.pos.x, mouse.pos.y))
                                                {
                                                        left = task->pix_left;
                                                        top = task->pix_top;
                                                        if (c->flags & CTRLF_BORDER)
                                                        {
                                                                left -= FONT_WIDTH;
                                                                top -= FONT_HEIGHT;
                                                        }
                                                        if (c->flags & CTRLF_CAPTURE_LEFT_MS)
                                                        {
                                                                while (mouse.lb && TaskValidate(task))
                                                                {
                                                                        if (c->left_click)
                                                                                (*c->left_click)(c, mouse.pos.x - left, mouse.pos.y - top, TRUE);
                                                                        WinMgrSleep;
                                                                }
                                                                if (c->left_click)
                                                                        (*c->left_click)(c, mouse.pos.x - left, mouse.pos.y - top, FALSE);
                                                                old_mouse.lb = FALSE;
                                                                goto wmt_start;
                                                        }
                                                        else
                                                        {
                                                                if (c->left_click)
                                                                        (*c->left_click)(c, mouse.pos.x - left, mouse.pos.y - top, TRUE);
                                                                old_mouse.lb = TRUE;
                                                                goto wmt_start;
                                                        }
                                                }
                                                c = c->next;
                                        }
                                }
                                if (old_mouse.lb && !mouse.lb)
                                {
                                        c = task->next_ctrl;
                                        while (c != &task->next_ctrl)
                                        {
                                                if (CtrlInside(c, mouse.pos.x, mouse.pos.y))
                                                {
                                                        left = task->pix_left;
                                                        top = task->pix_top;
                                                        if (c->flags & CTRLF_BORDER)
                                                        {
                                                                left -= FONT_WIDTH;
                                                                top -= FONT_HEIGHT;
                                                        }
                                                        if (c->left_click)
                                                                (*c->left_click)(c, mouse.pos.x - left, mouse.pos.y - top, FALSE);
                                                        old_mouse.lb = FALSE;
                                                        goto wmt_start;
                                                }
                                                c = c->next;
                                        }
                                }
                                if (mouse.rb && !old_mouse.rb)
                                {
                                        c = task->next_ctrl;
                                        while (c != &task->next_ctrl)
                                        {
                                                if (CtrlInside(c, mouse.pos.x, mouse.pos.y))
                                                {
                                                        left = task->pix_left;
                                                        top = task->pix_top;
                                                        if (c->flags & CTRLF_BORDER)
                                                        {
                                                                left -= FONT_WIDTH;
                                                                top -= FONT_HEIGHT;
                                                        }
                                                        if (c->flags & CTRLF_CAPTURE_RIGHT_MS)
                                                        {
                                                                while (mouse.rb && TaskValidate(task))
                                                                {
                                                                        if (c->right_click)
                                                                                (*c->right_click)(c, mouse.pos.x - left, mouse.pos.y - top, TRUE);
                                                                        WinMgrSleep;
                                                                }
                                                                if (c->right_click)
                                                                        (*c->right_click)(c, mouse.pos.x - left, mouse.pos.y - top, FALSE);
                                                                old_mouse.rb = FALSE;
                                                                goto wmt_start;
                                                        }
                                                        else
                                                        {
                                                                if (c->right_click)
                                                                        (*c->right_click)(c, mouse.pos.x - left, mouse.pos.y - top, TRUE);
                                                                old_mouse.rb = TRUE;
                                                                goto wmt_start;
                                                        }
                                                }
                                                c = c->next;
                                        }
                                }
                                if (old_mouse.rb && !mouse.rb)
                                {
                                        c = task->next_ctrl;
                                        while (c != &task->next_ctrl)
                                        {
                                                if (CtrlInside(c, mouse.pos.x, mouse.pos.y))
                                                {
                                                        left = task->pix_left;
                                                        top = task->pix_top;
                                                        if (c->flags & CTRLF_BORDER)
                                                        {
                                                                left -= FONT_WIDTH;
                                                                top -= FONT_HEIGHT;
                                                        }
                                                        if (c->right_click)
                                                                (*c->right_click)(c, mouse.pos.x - left, mouse.pos.y - top, FALSE);
                                                        old_mouse.rb = FALSE;
                                                        goto wmt_start;
                                                }
                                                c = c->next;
                                        }
                                }
                                if (mouse.has_wheel && my_mouse_z != mouse.pos.z)
                                {
                                        if (task == sys_focus_task)
                                        {
                                                c = task->next_ctrl;
                                                while (c != &task->next_ctrl)
                                                {
                                                        if (c->wheel_chg)
                                                        {
                                                                (*c->wheel_chg)(c, mouse.pos.z - my_mouse_z);
                                                                my_mouse_z = mouse.pos.z;
                                                                goto wmt_start;
                                                        }
                                                        c = c->next;
                                                }
                                                my_mouse_z = mouse.pos.z;
                                        }
                                        else if (!sys_focus_task)
                                                my_mouse_z = mouse.pos.z;
                                }
                        }

                        if (task == Fs)
                                goto wmt_start;

                        if (!Bt(&task->win_inhibit, WIf_SELF_MS_L) &&
                                (!TaskValidate(sys_focus_task) ||
                                !Bt(&sys_focus_task->win_inhibit, WIf_FOCUS_TASK_MS_L)))
                        {
                                if (!old_mouse.lb && mouse.lb)
                                {
                                        if (doc = WinCursorPosSet(task, mouse.pos.x, mouse.pos.y))
                                        {
                                                DocLock(doc);
                                                if (doc->doc_signature == DOC_SIGNATURE_VAL)
                                                {
                                                        doc_e = doc->cur_entry;
                                                        if (doc_e != doc)
                                                        {
                                                                if (doc_e->de_flags & DOCEF_HAS_BORDER)
                                                                        doc_e->de_flags |= DOCEF_SOLID_BORDER;
                                                        }
                                                }
                                                DocUnlock(doc);
                                                old_mouse.lb = TRUE;
                                                goto wmt_start;
                                        }
                                }
                        }
                        if (!Bt(&task->win_inhibit, WIf_SELF_MS_R) &&
                                (!TaskValidate(sys_focus_task) ||
                                !Bt(&sys_focus_task->win_inhibit, WIf_FOCUS_TASK_MS_R)))
                        {
                                if (!old_mouse.rb && mouse.rb)
                                {
                                        if (WinCursorPosSet(task, mouse.pos.x, mouse.pos.y))
                                        {
                                                old_mouse.rb = TRUE;
                                                goto wmt_start;
                                        }
                                }
                        }
                        if (!Bt(&task->win_inhibit, WIf_SELF_BORDER) && has_border &&
                                (!TaskValidate(sys_focus_task) ||
                                !Bt(&sys_focus_task->win_inhibit, WIf_FOCUS_TASK_BORDER)))
                        {
                                if (old_mouse.lb && !mouse.lb)
                                {
                                        if (mouse.pos_text.y == task->win_top - 1)
                                        {
                                                if (task->win_left <= mouse.pos_text.x < task->win_left + 4)
                                                {
                                                        TaskMessage(task, 0, MESSAGE_KEY_DOWN, CH_CTRLM, 0x43200000432, 0);
                                                        old_mouse.lb = FALSE;
                                                        goto wmt_start;
                                                }
                                                else if (task->win_right - 2 <= mouse.pos_text.x <= task->win_right)
                                                {
                                                        if (DocPut(task))
                                                                TaskMessage(task, 0, MESSAGE_KEY_DOWN, CH_SHIFT_ESC, 0, 0);
                                                        else
                                                                Kill(task, FALSE);
                                                        old_mouse.lb = FALSE;
                                                        goto wmt_start;
                                                }
                                        }
                                }
                        }
                        if (!Bt(&task->win_inhibit, WIf_SELF_MS_L) &&
                                (!TaskValidate(sys_focus_task) ||
                                !Bt(&sys_focus_task->win_inhibit, WIf_FOCUS_TASK_MS_L)))
                        {
                                if (old_mouse.lb && !mouse.lb)
                                {
                                        if (doc = WinCursorPosSet(task, mouse.pos.x, mouse.pos.y, FALSE))
                                        {
                                                do message_code = WinMgrSleep;
                                                while (TaskValidate(task) && (mouse.lb || mouse.left_dbl_time));
                                                if (TaskValidate(task))
                                                {
                                                        if (message_code == MESSAGE_MS_L_UP)
                                                        {
                                                                if (doc->doc_signature == DOC_SIGNATURE_VAL)
                                                                {
                                                                        DocLock(doc);
                                                                        if (TaskValidate(task))
                                                                        {
                                                                                if (doc->doc_signature == DOC_SIGNATURE_VAL)
                                                                                {
                                                                                        doc_e = doc->cur_entry;
                                                                                        if (doc_e!=doc)
                                                                                        {
                                                                                                if (doc_e->de_flags & DOCEF_HAS_BORDER)
                                                                                                        doc_e->de_flags &= ~DOCEF_SOLID_BORDER;
                                                                                                if (doc_e->de_flags & (DOCEF_TREE | DOCEF_LIST |
                                                                                                        DOCEF_LINK | DOCEF_CHECK_COLLAPSABLE |
                                                                                                        DOCEF_LEFT_CB | DOCEF_LEFT_MACRO | DOCEF_LEFT_EXP))
                                                                                                {
                                                                                                        TaskMessage(task, 0, MESSAGE_KEY_DOWN, CH_SPACE, 0, 0);
                                                                                                }
                                                                                        }
                                                                                }
                                                                                DocUnlock(doc);
                                                                        }
                                                                }
                                                        }
                                                        else if (message_code == MESSAGE_MS_L_D_UP)
                                                                TaskMessage(task, 0, MESSAGE_KEY_DOWN, CH_ESC, 0, 0);
                                                }
                                                old_mouse.lb = FALSE;
                                                goto wmt_start;
                                        }
                                }
                        }

                        if (!Bt(&task->win_inhibit,WIf_SELF_MS_R)&&
                                (!TaskValidate(sys_focus_task) ||
                                !Bt(&sys_focus_task->win_inhibit, WIf_FOCUS_TASK_MS_R)))
                        {
                                if (old_mouse.rb && !mouse.rb)
                                {
                                        if (doc = WinCursorPosSet(task, mouse.pos.x, mouse.pos.y, FALSE))
                                        {
                                                do message_code = WinMgrSleep;
                                                while (TaskValidate(task) && (mouse.rb || mouse.right_dbl_time));
                                                if (TaskValidate(task))
                                                {
                                                        if (message_code == MESSAGE_MS_R_UP)
                                                        {
                                                                if (doc->doc_signature == DOC_SIGNATURE_VAL)
                                                                {
                                                                        DocLock(doc);
                                                                        if (TaskValidate(task))
                                                                        {
                                                                                if (doc->doc_signature == DOC_SIGNATURE_VAL)
                                                                                {
                                                                                        doc_e = doc->cur_entry;
                                                                                        if (doc_e != doc) {
                                                                                                if (doc_e->de_flags & (DOCEF_LINK |
                                                                                                        DOCEF_RIGHT_CB | DOCEF_RIGHT_MACRO | DOCEF_RIGHT_EXP))
                                                                                                {
                                                                                                        TaskMessage(task, 0, MESSAGE_KEY_DOWN, '\n', 0, 0);
                                                                                                }
                                                                                        }
                                                                                }
                                                                                DocUnlock(doc);
                                                                        }
                                                                }
                                                        }
                                                        else if (message_code == MESSAGE_MS_R_D_UP)
                                                                TaskMessage(task, 0, MESSAGE_KEY_DOWN, CH_SHIFT_ESC, 0, 0);
                                                }
                                                old_mouse.rb = FALSE;
                                                goto wmt_start;
                                        }
                                }
                        }

                        if (!Bt(&task->win_inhibit,WIf_SELF_BORDER) && has_border &&
                                (!TaskValidate(sys_focus_task) ||
                                !Bt(&sys_focus_task->win_inhibit, WIf_FOCUS_TASK_BORDER)))
                        {
                                if (mouse.lb && !old_mouse.lb)
                                {
                                        if (task->win_top == mouse.pos_text.y + 1 &&
                                                task->win_left - 1 <= mouse.pos_text.x <= task->win_right + 1)
                                        {
                                                if (task->win_left <= mouse.pos_text.x < task->win_left + 4)
                                                {
                                                        old_mouse.lb = TRUE;
                                                        goto wmt_start;
                                                }
                                                if (task->win_right - 2 <= mouse.pos_text.x <= task->win_right)
                                                {
                                                        old_mouse.lb = TRUE;
                                                        goto wmt_start;
                                                }
                                                x = mouse.pos_text.x - task->win_left;
                                                if (mouse.lb)
                                                {
                                                        WinToTop(task);
                                                        while (mouse.lb && TaskValidate(task))
                                                        {
                                                                WinHorz(mouse.pos_text.x - x, task->win_width - 1 + mouse.pos_text.x - x, task);
                                                                WinVert(mouse.pos_text.y + 1, task->win_height + mouse.pos_text.y, task);
                                                                WinMgrSleep;
                                                        }
                                                }
                                                old_mouse.lb = FALSE;
                                                goto wmt_start;
                                        }
                                        if (task->win_left == mouse.pos_text.x + 1 &&
                                                task->win_top - 1 <= mouse.pos_text.y <= task->win_bottom + 1)
                                        {
                                                y = mouse.pos_text.y - task->win_top;
                                                if (mouse.lb)
                                                {
                                                        WinToTop(task);
                                                        while (mouse.lb && TaskValidate(task))
                                                        {
                                                                WinHorz(mouse.pos_text.x + 1, task->win_width + mouse.pos_text.x, task);
                                                                WinVert(mouse.pos_text.y - y, task->win_height - 1 + mouse.pos_text.y - y, task);
                                                                WinMgrSleep;
                                                        }
                                                }
                                                old_mouse.lb = FALSE;
                                                goto wmt_start;
                                        }
                                        if (task->win_right + 1 == mouse.pos_text.x &&
                                                task->win_bottom + 1 == mouse.pos_text.y)
                                        {
                                                if (mouse.lb)
                                                {
                                                        WinToTop(task);
                                                        while (mouse.lb && TaskValidate(task))
                                                        {
                                                                WinHorz(task->win_left, mouse.pos_text.x - 1, task);
                                                                WinVert(task->win_top, mouse.pos_text.y - 1, task);
                                                                WinMgrSleep;
                                                        }
                                                }
                                                old_mouse.lb = FALSE;
                                                goto wmt_start;
                                        }
                                        if (task->win_bottom == mouse.pos_text.y - 1 &&
                                                task->win_left <= mouse.pos_text.x <= task->win_right)
                                        {
                                                if (mouse.lb)
                                                {
                                                        WinToTop(task);
                                                        while (mouse.lb && TaskValidate(task))
                                                        {
                                                                WinVert(task->win_top, mouse.pos_text.y - 1, task);
                                                                WinMgrSleep;
                                                        }
                                                }
                                                old_mouse.lb = FALSE;
                                                goto wmt_start;
                                        }
                                        if (task->win_right == mouse.pos_text.x - 1 &&
                                                task->win_top <= mouse.pos_text.y <= task->win_bottom)
                                        {
                                                if (mouse.lb)
                                                {
                                                        WinToTop(task);
                                                        while (mouse.lb && TaskValidate(task))
                                                        {
                                                                WinHorz(task->win_left, mouse.pos_text.x - 1, task);
                                                                WinMgrSleep;
                                                        }
                                                }
                                                old_mouse.lb = FALSE;
                                                goto wmt_start;
                                        }
                                }
                        }
                }
                catch
                {
                        Beep;
                        Fs->catch_except = TRUE;
                        task = Fs;
                }
        }
}