<1>/* Graphics Not Rendered in HTML */
        
        <2>/* Graphics Not Rendered in HTML */
        
        <3>/* Graphics Not Rendered in HTML */
        
        <4>/* Graphics Not Rendered in HTML */
        
        <5>/* Graphics Not Rendered in HTML */
        
        <6>/* Graphics Not Rendered in HTML */
        
        
        <7>/* Graphics Not Rendered in HTML */
        
         
        <8>/* Graphics Not Rendered in HTML */
        
        
        <9>/* Graphics Not Rendered in HTML */
        
        
        <10>/* Graphics Not Rendered in HTML */
        
        
        <11>/* Graphics Not Rendered in HTML */
        
        
        
        
        
        
        
        <12>/* Graphics Not Rendered in HTML */
        
        
         
        
        <13>/* Graphics Not Rendered in HTML */
        
        <14>/* Graphics Not Rendered in HTML */
        
        <15>/* Graphics Not Rendered in HTML */
        
        
        <16>/* Graphics Not Rendered in HTML */

#define PSM_NOTE_SPACING                        9
#define PSM_DURATIONS_NUM                       12

F64 psm_durations[PSM_DURATIONS_NUM + 1] =
                {2 * .25 / 3, .25, 2 * .5 / 3, .5, 2.0 / 3.0, 0.5 * 1.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 1000000.0};
U8 *psm_duration_list = "st\0s\0et\0e\0qt\0e.\0q\0q.\0h\0h.\0w\0w.\0";
U8 *psm_duration_imgs[PSM_DURATIONS_NUM] = {<1>, <1>, <2>, <2>, <3>, <2>, <3>, <3>, <4>, <4>, <5>, <5>};
Bool psm_triplet_durations[PSM_DURATIONS_NUM] =
                {TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE};

Bool PsmBlink()
{
        if (Blink || psm.playing)
                return TRUE;
        else
                return FALSE;
}

Bool PsmHasWords(U8 *st)
{
        if (st && *st && (StrLen(st) > 1 || *st != CH_SPACE))
                return TRUE;
        else
                return FALSE;
}

Bool PsmIsDotted(I64 duration)
{
        U8 *st = ListSub(duration, psm_duration_list);

        if (st[1] == '.')
                return TRUE;
        else
                return FALSE;
}

U0 PsmMarkSel(I64 x1, I64 x2, Bool sel)
{
        PsmNote *tmpn = psm.head.next;

        while (tmpn != &psm.head)
        {
                if (sel)
                {
                        if (x1 <= tmpn->x <= x2)
                                tmpn->flags |= PSMF_SEL;
                }
                else
                        tmpn->flags &= ~PSMF_SEL;
                tmpn = tmpn->next;
        }
}

U0 PsmSetWidth(PsmNote *tmpn)
{
        if (tmpn->type == PSMT_METER)
                tmpn->width = 12;
        else
        {
                tmpn->width = PSM_NOTE_SPACING;
                if (PsmIsDotted(tmpn->duration))
                        tmpn->width += PSM_NOTE_SPACING / 2;
                if (Bt(&tmpn->flags, PSMf_SHARP) || Bt(&tmpn->flags, PSMf_FLAT))
                        tmpn->width += PSM_NOTE_SPACING;
        }
}

U0 PsmSetOctave(I64 octave)
{
        I64                      i;
        U8                       buf[STR_LEN];
        CMenuEntry      *tmpse;

        for (i = 1; i <= 7; i++)
        {
                StrPrint(buf, "Sound/Octave%d", i);
                if (tmpse = MenuEntryFind(Fs->cur_menu, buf))
                {
                        if (i == octave)
                                tmpse->checked = TRUE;
                        else
                                tmpse->checked = FALSE;
                }
        }
}

U0 DrawNote(CDC *dc, I64 x, I64 y, I64 duration)
{
        if (0 <= duration <= PSM_DURATIONS_NUM)
        {
                Sprite3(dc, x, y, 0, psm_duration_imgs[duration]);
                if (psm_triplet_durations[duration])
                        Sprite3(dc, x, y, 0, <16>);
                if (PsmIsDotted(duration))
                        Sprite3(dc, x, y, 0, <15>);
        }
}

U0 DrawTimeSignature(CDC *dc, I64 x, I64 y, I64 top, I64 bottom)
{
        GrPrint(dc, x, y, "%d", top);
        GrPrint(dc, x, y + FONT_HEIGHT, "%d", bottom);
}

U0 PsmRecalcNoteXY()
{
        F64              measure_len = 4, measure_left = measure_len;
        PsmNote *tmpn = psm.head.next;
        I64              x = 8 - psm.screen_x, ona, note, octave;

        while (TRUE)
        {
                tmpn->x = x;
                tmpn->y = 50;
                if (tmpn == &psm.head)
                        break;
                else
                {
                        if (tmpn->type != PSMT_METER)
                        {
                                if (tmpn->ona)
                                {
                                        ona = tmpn->ona;
                                        if (Bt(&tmpn->flags, PSMf_SHARP))
                                                ona--;
                                        if (Bt(&tmpn->flags, PSMf_FLAT))
                                                ona++;
                                        octave  = Ona2Octave(ona);
                                        note    = Ona2Note  (ona);
                                        note = music.note_map[*ListSub(note, psm_note_list) - 'A'];
                                        if (note < 3)
                                                octave++;
                                        tmpn->y = (15 + (psm_note_map[note] - 7 * (octave - 4))) * 4;
                                }
                        }
                        x += tmpn->width;
                        if (tmpn->type == PSMT_METER)
                        {
                                measure_len = tmpn->meter_top * 4.0 / tmpn->meter_bottom;
                                measure_left = 0;
                        }
                        else
                                measure_left -= psm_durations[tmpn->duration];
                        if (measure_left < 0.001)
                        {
                                x += PSM_NOTE_SPACING;
                                measure_left = measure_len;
                        }
                }
                tmpn = tmpn->next;
        }
}

U0 DrawIt(CTask *task, CDC *dc)
{
        PsmNote *tmpn;
        I64              i, x, y, 
                         w = task->pix_width;
        F64              measure_len = 4, measure_left = measure_len;

        dc->color = BLACK;
        for (i = 1; i < 6; i++)
                GrLine(dc, 0, i * 8, w, i * 8);
        for (i = 7; i < 12; i++)
                GrLine(dc, 0, i * 8, w, i * 8);

        PsmRecalcNoteXY;
        if (psm.cur_note->x < 64)
        {
                psm.screen_x -= 128;
                PsmRecalcNoteXY;
        }
        if (psm.cur_note->x >= GR_WIDTH - 64)
        {
                psm.screen_x += 128;
                PsmRecalcNoteXY;
        }

        tmpn = psm.head.next;
        while (tmpn != &psm.head)
        {
                x = tmpn->x;
                y = tmpn->y;
                if (measure_left < 0.001)
                {
                        dc->color = BLACK;
                        GrLine(dc, x - PSM_NOTE_SPACING, 8, x - PSM_NOTE_SPACING, 11 * 8);
                        measure_left = measure_len;
                }
                if (tmpn->type == PSMT_METER)
                {
                        if (tmpn == psm.cur_note && PsmBlink)
                                dc->color = BROWN;
                        else
                                dc->color = BLACK;
                        DrawTimeSignature(dc, x, 5 * 8, tmpn->meter_top, tmpn->meter_bottom);
                        measure_len = tmpn->meter_top * 4.0 / tmpn->meter_bottom;
                        measure_left = 0;
                }
                else
                {
                        if (tmpn == psm.cur_note && PsmBlink)
                        {
                                dc->color = BROWN;
                                GrPrint(dc, x + 8, y, "%s", tmpn->word);
                        }
                        else if (tmpn->flags & PSMF_SEL)
                                dc->color = RED;
                        else
                        {
                                if (tmpn->ona)
                                        dc->color = BLACK;
                                else
                                        dc->color = LTGRAY;
                                if (PsmHasWords(tmpn->word))
                                        dc->color = GREEN;
                        }
                        DrawNote(dc, x, y, tmpn->duration);
                        if (PsmIsDotted(tmpn->duration))
                                x += PSM_NOTE_SPACING/2;
                        if (Bt(&tmpn->flags, PSMf_SHARP))
                                Sprite3(dc, x, y, 0, <13>);
                        else if (Bt(&tmpn->flags, PSMf_FLAT))
                                Sprite3(dc, x, y, 0, <14>);
                        measure_left -= psm_durations[tmpn->duration];
                }
                tmpn = tmpn->next;
        }

        if (psm.cur_note == &psm.head && PsmBlink)
                dc->color = BROWN;
        else
                dc->color = BLACK;
        Sprite3(dc, psm.head.x, 50, 0, <12>);
}

#define PSM_NOTE_BOX_X  220
#define PSM_NOTE_BOX_Y  (13 * FONT_HEIGHT + 14)
U0 PsmSetPickNoteBoxX(I64 duration, I64 *x)
{
        I64 i;

        *x = PSM_NOTE_BOX_X;
        for (i = 0; i < duration; i++)
        {
                if (PsmIsDotted(i))
                        *x += PSM_NOTE_SPACING / 2;
                *x += PSM_NOTE_SPACING + 4;
        }
}

I64 PsmGetPickNoteBoxDuration(I64 xx, I64 yy)
{
        I64 i, x1, x2;

        if (PSM_NOTE_BOX_Y  -14 <= yy < PSM_NOTE_BOX_Y + 6)
        {
                for (i = 0; i < PSM_DURATIONS_NUM; i++)
                {
                        PsmSetPickNoteBoxX(i, &x1);
                        PsmSetPickNoteBoxX(i + 1, & x2);
                        if (x1 <= xx + PSM_NOTE_SPACING / 2 < x2)
                                return i;
                }
        }

        return -1;
}

U0 DrawPickNoteBox()
{
        I64 i, x;

        for (i = 0; i < PSM_DURATIONS_NUM; i++)
        {
                PsmSetPickNoteBoxX(i, &x);
                if (PsmIsDotted(i))
                        psm.dc2->color = RED;
                else if (psm_triplet_durations[i])
                        psm.dc2->color = LTRED;
                else
                        psm.dc2->color = BLACK;
                DrawNote(psm.dc2, x, PSM_NOTE_BOX_Y, i);
        }
}

#define PSM_TOOLS_X             450
#define PSM_TOOLS_Y             13 * FONT_HEIGHT

U0 DrawPickTools()
{
        if (psm.tool == PSMTT_BOX_TOOL)
                psm.dc2->color = ROPF_DITHER + WHITE << 16 + RED;
        else
                psm.dc2->color = ROPF_DITHER + WHITE << 16 + BLACK;
        GrBorder(psm.dc2, PSM_TOOLS_X, PSM_TOOLS_Y, PSM_TOOLS_X + 10, PSM_TOOLS_Y + 10);

        if (psm.tool == PSMTT_PTR_TOOL)
                psm.dc2->color = RED;
        else
                psm.dc2->color = BLACK;
        (*gr.fp_draw_mouse)(psm.dc2, PSM_TOOLS_X + 15, PSM_TOOLS_Y);
        psm.dc2->color = BLACK;
}

Bool PsmGetPickToolBox(I64 xx, I64 yy)
{
        if (PSM_TOOLS_X <= xx < PSM_TOOLS_X + 27 && PSM_TOOLS_Y <= yy < PSM_TOOLS_Y + 15)
        {
                PsmMarkSel(0, 0, FALSE);
                if (xx < PSM_TOOLS_X + 13)
                        psm.tool = PSMTT_BOX_TOOL;
                else
                        psm.tool = PSMTT_PTR_TOOL;
                return TRUE;
        }
        else
                return FALSE;
}

#define PSM_METERS_NUM  7
I64 meter_tops[PSM_METERS_NUM]          = {2, 3, 4, 5, 6, 7, 9}, 
        meter_bottoms[PSM_METERS_NUM]   = {4, 4, 4, 4, 8, 8, 8};

#define PSM_METER_X             485
#define PSM_METER_Y             13 * FONT_HEIGHT
#define PSM_METER_W             12
Bool PsmGetPickMeterBox(I64 xx, I64 yy, I64 *top, I64 *bottom)
{
        I64 i;

        if (PSM_METER_X <= xx < PSM_METER_X + PSM_METER_W * PSM_METERS_NUM &&
                PSM_METER_Y <= yy < PSM_METER_Y + 2 * FONT_HEIGHT)
        {
                i = (xx - PSM_METER_X) / PSM_METER_W;
                *top = meter_tops[i];
                *bottom = meter_bottoms[i];
                return TRUE;
        }
        else
                return FALSE;
}

U0 DrawPickMeterBox()
{
        I64 i;

        psm.dc2->color = BLACK;
        for (i = 0; i < PSM_METERS_NUM; i++)
                DrawTimeSignature(psm.dc2, PSM_METER_X + i * PSM_METER_W, PSM_METER_Y, meter_tops[i], meter_bottoms[i]);
}

U0 DrawDC2()
{
        DCFill;
        DrawPickNoteBox;
        DrawPickMeterBox;
        DrawPickTools;
}


<17>/* Graphics Not Rendered in HTML */
 




U0 PsmMenu(I64 psm_octave)
{
        DocClear;
        "$BG,WHITE$$FD,GREEN$$CM,0,12$\n";
        Sprite(<17>);
        '\n\n\n\n\n';

        DrawDC2;

        "$LTGREEN$<SPACE>$FG$\t\tRest\n"
        "$LTGREEN$<BACKSPACE>$FG$\tDeletes Last Note\n"
        "$LTGREEN$Left Mouse$FG$\tDrag note or shift word\n"
        "$LTGREEN$Right Mouse$FG$\tChange duration or set word\n";
        Sprite(<6>, "$SP+LIS,\"\","
                                "LM=\"Message(MESSAGE_KEY_DOWN,0,SCF_CTRL|SC_CURSOR_LEFT);\",BI=%d$");
        "   ";
        if (psm.playing)
                Sprite(<9>, "$SP,\"\",LM=\"x\",BI=%d$");
        else
                Sprite(<8>, "$SP,\"\",LM=\"x\",BI=%d$");
        "   ";
        if (psm.record_entry->checked)
        {
                psm.record_entry->checked = TRUE;
                Sprite(<10>, "$SP,\"\",LM=\"z\",BI=%d$");
        }
        else
                Sprite(<11>, "$SP,\"\",LM=\"z\",BI=%d$");
        "   ";
        Sprite(<7>, "$SP+LIS,\"\","
                                "LM=\"Message(MESSAGE_KEY_DOWN,0,SCF_CTRL|SC_CURSOR_RIGHT);\",BI=%d$");
        "$CM+LX,0,6$";
        PsmSetOctave(psm_octave);
        Refresh(2);
}