📄 dismgr.c
字号:
memmove (dismgr_state.framebuf,
dismgr_state.framebuf + 1,
prompt_wid_minus_one);
glyph_column = dismgr_state.glyph[dismgr_state.glyph_index++];
dismgr_state.framebuf[prompt_wid_minus_one] = glyph_column;
}
else
{
memmove (dismgr_state.framebuf + 1,
dismgr_state.framebuf,
prompt_wid_minus_one);
glyph_column = dismgr_state.glyph[dismgr_state.glyph_wid - dismgr_state.glyph_index++ - 1];
dismgr_state.framebuf[0] = glyph_column;
}
#endif
PioSet (1 << 8, 1 << 8);
/*
BP
PioSet (1 << 10, 0 << 10);
*/
/*
* Check for end-of-glyph, and if so move to the next prompt character.
*/
PioSet (1 << 10, 1 << 10);
if (dismgr_state.glyph_index == dismgr_state.glyph_wid)
{
bool fetch_next_glyph = TRUE;
zero_width_glyph:
/*
* Check for end-of-prompt, and if so do the next thing.
*/
if (++dismgr_state.prompt_index == dismgr_state.prompt_len)
{
switch (dismgr_state.next_thing)
{
case DISMGR_NEXT_THING_STOP:
dismgr_state.next_thing = DISMGR_NEXT_THING_STOP_NOW;
fetch_next_glyph = FALSE;
dismgr_state.delay = DISMGR_FINAL_DELAY;
break;
case DISMGR_NEXT_THING_CHANGE_DIR_THEN_STOP:
dismgr_state.next_thing = DISMGR_NEXT_THING_STOP;
/* deliberate fall-through */
case DISMGR_NEXT_THING_CHANGE_DIR:
dismgr_state.incrementing = !dismgr_state.incrementing;
#if DISMGR_SCROLL_SIZE > 1
DismgrRenderFramebuffer (step == DISMGR_SCROLL_SIZE - 1, FALSE);
#else
DismgrRenderFramebuffer (TRUE, FALSE);
#endif
fetch_next_glyph = FALSE;
dismgr_state.delay = DISMGR_CHANGE_DELAY;
break;
case DISMGR_NEXT_THING_CONTINUE:
dismgr_state.prompt_index = 0;
break;
default: /* impossible */
Panic ();
}
}
if (fetch_next_glyph)
{
/*
* Fetch the next glyph.
*/
dismgr_state.glyph_wid = FontGetGlyphAny (dismgr_state.prompt_font,
dismgr_state.prompt[dismgr_state.incrementing ?
dismgr_state.prompt_index :
dismgr_state.prompt_len - dismgr_state.prompt_index - 1],
dismgr_state.glyph, sizeof (dismgr_state.glyph));
/*
* The glyph must exist if we get here (otherwise we'd either
* have rejected the prompt in DismgrDisplayPrompt() or panicked
* in the FontGetGlyphAny() above) ...
* but it might be of zero width.
*/
if (dismgr_state.glyph_wid == 0)
{
goto zero_width_glyph; /* yes, I know */
}
dismgr_state.glyph_index = 0;
}
#if DISMGR_SCROLL_SIZE > 1
else
{
break;
}
#endif
}
PioSet (1 << 8, 1 << 8);
/*
BP
PioSet (1 << 10, 0 << 10);
*/
#if DISMGR_SCROLL_SIZE > 1
}
#endif
PioSet (1 << 8, 1 << 8);
/*
BP
PioSet (1 << 10, 1 << 10);
*/
t = VmGetClock () - t;
#if 0
if (TRUE)
#else
if (t >= DISMGR_SCROLL_DELAY)
#endif
{
PioSet (1 << 8, 1 << 8);
/*
BP
PioSet (1 << 10, 0 << 10);
*/
MessageSendLater (&dismgr_state.task, 0, NULL, 0);
return;
}
PioSet (1 << 8, 1 << 8);
/*
BP
PioSet (1 << 10, 0 << 10);
*/
MessageSendLater (&dismgr_state.task, 0, NULL, DISMGR_SCROLL_DELAY - t);
return;
}
/*
* Cancel any scrolling.
*/
static void DismgrCancelScrolling (void)
{
if (dismgr_state.framebuf != NULL)
{
MessageCancelFirst (&dismgr_state.task, 0);
free (dismgr_state.framebuf);
dismgr_state.framebuf = NULL;
}
}
/*
* Check whether the specified region overlaps a scrolling region;
* if so stop the scrolling.
*/
static void DismgrCancelScrollingIfOverlap (uint8 first, uint8 last)
{
if (dismgr_state.framebuf != NULL)
{
uint8 prompt_last = dismgr_state.prompt_first + dismgr_state.prompt_wid - 1;
if ((first >= dismgr_state.prompt_first &&
first <= prompt_last) ||
(last >= dismgr_state.prompt_first &&
last <= prompt_last))
{
DismgrCancelScrolling ();
}
}
}
/*
* Clear the display.
*/
DismgrResult DismgrClear (void)
{
if (!LcdClear ()) /* this also clears the hardware icons */
{
return DISMGR_RESULT_LCD_OUTPUT_FAIL;
}
DismgrCancelScrolling ();
return DISMGR_RESULT_SUCCESS;
}
/*
* Clear part of the display.
*/
DismgrResult DismgrClearPart (uint8 clear_first, uint8 clear_last)
{
#ifdef DISMGR_LOW_CONST
uint8 zeroes[DISMGR_MAX_ICON_WID] = { 0 /* , 0, 0, 0, ... */ };
uint8 clear_pos, clear_pos2;
#endif
uint8 clear_wid;
#ifndef DISMGR_LOW_CONST
static const uint8 zeroes[DISMGR_MAX_COLUMN + 1] /* = { 0, 0, 0, 0, ... } */;
#endif
/*
* Sanity-check the requested placement.
*/
if (clear_first > clear_last ||
clear_last > DISMGR_MAX_COLUMN)
{
return DISMGR_RESULT_COLUMN_INVALID;
}
/*
* Clear, cancelling any scrolling if overlapping.
*/
DismgrCancelScrollingIfOverlap (clear_first, clear_last);
#ifdef DISMGR_LOW_CONST
for (clear_pos = clear_first; clear_pos <= clear_last; clear_pos = clear_pos2)
{
clear_pos2 = clear_pos + sizeof (zeroes);
if (clear_pos2 > clear_last)
{
clear_wid = clear_last - clear_pos + 1;
}
else
{
clear_wid = sizeof (zeroes);
}
if (!LcdOutput (zeroes, clear_wid, LCD_COLUMN_LEFT + clear_pos, LCD_LINE_BOTTOM) ||
!LcdOutput (zeroes, clear_wid, LCD_COLUMN_LEFT + clear_pos, LCD_LINE_TOP))
{
return DISMGR_RESULT_LCD_OUTPUT_FAIL;
}
}
#else
clear_wid = clear_last - clear_first + 1;
if (!LcdOutput (zeroes, clear_wid, LCD_COLUMN_LEFT + clear_first, LCD_LINE_BOTTOM) ||
!LcdOutput (zeroes, clear_wid, LCD_COLUMN_LEFT + clear_first, LCD_LINE_TOP))
{
return DISMGR_RESULT_LCD_OUTPUT_FAIL;
}
#endif
return DISMGR_RESULT_SUCCESS;
}
/*
* Display a prompt, optionally with scrolling.
*/
DismgrResult DismgrDisplayPrompt (const ucs2char *prompt, uint8 prompt_len, uint8 prompt_first, uint8 prompt_last, bool left_to_right, DismgrScrollType scroll_type)
{
uint8 prompt_wid;
#ifndef FONT_REPLACEMENT_CHARACTER
uint8 prompt_index;
#endif
DismgrResult result = DISMGR_RESULT_SUCCESS;
#ifndef NOBF
ASSERT (prompt_len < (1 << DISMGR_BITS_PROMPT_LEN));
#endif
ASSERT (left_to_right == FALSE || left_to_right == TRUE);
ASSERT (scroll_type < DISMGR_SCROLL_TYPE_LIMIT);
/*
* Sanity-check the requested placement.
*/
if (prompt_first > prompt_last ||
prompt_last > DISMGR_MAX_COLUMN)
{
return DISMGR_RESULT_COLUMN_INVALID;
}
#ifndef FONT_REPLACEMENT_CHARACTER
/*
* Check the prompt for unknown glyphs.
*/
for (prompt_index = 0; prompt_index < prompt_len; ++prompt_index)
{
if (FontGetGlyphAny (dismgr_state.prompt_font, prompt[prompt_index], NULL, 0) == (size_t) -1)
{
return DISMGR_RESULT_GLYPH_NOT_FOUND;
}
}
#endif
/*
* Construct the initial framebuffer, after cancelling any scrolling.
*/
DismgrCancelScrolling ();
prompt_wid = prompt_last - prompt_first + 1;
if ((dismgr_state.framebuf = malloc (prompt_wid)) == NULL)
{
return DISMGR_RESULT_MALLOC_FAIL;
}
dismgr_state.prompt = prompt;
dismgr_state.prompt_len = prompt_len;
dismgr_state.prompt_first = prompt_first;
dismgr_state.prompt_wid = prompt_wid;
dismgr_state.incrementing = dismgr_state.left_to_right = left_to_right;
dismgr_state.prompt_font = dismgr_state.font;
dismgr_state.delay = 0;
if (DismgrRenderFramebuffer (FALSE, FALSE))
{
/*
* Prompt fits.
* If scrolling was requested, it's not needed after all; report this.
*/
if (scroll_type != DISMGR_SCROLL_TYPE_NONE)
{
scroll_type = DISMGR_SCROLL_TYPE_NONE;
result = DISMGR_RESULT_FITS;
}
}
else
{
/*
* Prompt does not fit.
* If no scrolling was requested, report this, and add dots.
*/
if (scroll_type == DISMGR_SCROLL_TYPE_NONE)
{
result = DISMGR_RESULT_TRUNCATED;
DismgrRenderFramebuffer (TRUE, TRUE);
}
}
/*
* Output the initial framebuffer;
* abort on failure.
*/
if (!DismgrOutputPrompt ())
{
result = DISMGR_RESULT_LCD_OUTPUT_FAIL;
}
/*
* Do we need to do any scrolling?
*/
else if (scroll_type == DISMGR_SCROLL_TYPE_NONE)
{
/*
* No; shut down.
*/
free (dismgr_state.framebuf);
dismgr_state.framebuf = NULL;
}
else
{
/*
* Yes; set up the rest of the state and kick off the scrolling.
*/
switch (scroll_type)
{
case DISMGR_SCROLL_TYPE_ONEWAY_ONCE:
dismgr_state.next_thing = DISMGR_NEXT_THING_STOP;
break;
case DISMGR_SCROLL_TYPE_RETURN_ONCE:
dismgr_state.next_thing = DISMGR_NEXT_THING_CHANGE_DIR_THEN_STOP;
break;
case DISMGR_SCROLL_TYPE_ONEWAY_ENDLESS:
dismgr_state.next_thing = DISMGR_NEXT_THING_CONTINUE;
break;
case DISMGR_SCROLL_TYPE_RETURN_ENDLESS:
dismgr_state.next_thing = DISMGR_NEXT_THING_CHANGE_DIR;
break;
default:
Panic ();
}
MessageSendLater (&dismgr_state.task, 0, NULL, DISMGR_INITIAL_DELAY);
}
return result;
}
/*
* Select the font to use for prompts.
*/
DismgrResult DismgrSelectFont (FontId font)
{
#ifndef NOBF
if (font >= (1 << DISMGR_BITS_FONT))
{
return DISMGR_RESULT_FONT_INVALID;
}
#endif
dismgr_state.font = font;
return DISMGR_RESULT_SUCCESS;
}
/*
* Initialise the display manager.
* Must be the first function called in this file.
*/
DismgrResult DismgrInit (void)
{
if (!LcdInit ())
{
return DISMGR_RESULT_LCD_INIT_FAIL;
}
if (FontInit () == 0)
{
return DISMGR_RESULT_FONT_INIT_FAIL;
}
PioSetDir (1 << 8, 1 << 8);
PioSet (1 << 8, 1 << 8);
/*
BP
PioSetDir (1 << 10, 1 << 10);
PioSet (1 << 10, 1 << 10);
*/
dismgr_state.task.handler = DismgrScroll;
dismgr_state.framebuf = NULL;
return DISMGR_RESULT_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -