//Simple and fancy way of searching

//See ::/Apps/Vocabulary/VocabQuiz.CC
//for another example of dictionary usage.

#define ROWS_NUM    20
#define COLS_NUM    20
#define DIM_MAX     MaxI64(ROWS_NUM, COLS_NUM)

U8 m[ROWS_NUM][COLS_NUM];

U0 Init()
{
    I64 x, y;

    for (y = 0; y < ROWS_NUM; y++)
        for (x = 0; x < COLS_NUM; x++)
            m[y][x] = 'A' + RandU16 % 26;
}

U0 Display()
{
    I64 x, y;

    for (y = 0; y < ROWS_NUM; y++)
    {
        for (x = 0; x < COLS_NUM; x++)
            '' m[y][x];
        '\n';
    }
}

U0 GetWord(U8 *dst, I64 x, I64 y, I64 dx, I64 dy)
{
    while (0 <= x < COLS_NUM && 0 <= y < ROWS_NUM)
    {
        *dst++ = m[y][x];
        y += dy;
        x += dx;
    }
    *dst = 0;
}

//************************************
U0 Search(I64 dx, I64 dy)
{
    I64 x, y, i, n;
    U8  buf[DIM_MAX + 1], *ptr;

    for (y = 0; y < ROWS_NUM; y++)
        for (x = 0; x < COLS_NUM; x++)
        {
            GetWord(buf, x, y, dx, dy);
            n = StrLen(buf);
            for (i = n; i > 2; i--)
            {
                buf[i] = 0;
                if ((ptr = ACDWordPtAt(buf)) && *ptr++ == ACD_WORD_CHAR && !StrICompare(ptr, buf))
                {
                    "%s ", buf;
                }
            }
        }
}

U0 SimpleWordSearch()
{
    Search( 1,  0);
    Search( 0,  1);
    Search(-1,  0);
    Search( 0, -1);
    Search( 1,  1);
    Search(-1, -1);
    Search( 1, -1);
    Search(-1,  1);
    '\n';
}

//************************************
U8  words[ROWS_NUM * COLS_NUM * 8][DIM_MAX + 1];
U8 *word_ptrs[ROWS_NUM * COLS_NUM * 8];

U0 CollectWords(I64 dx, I64 dy, I64 *_n)
{
    I64 x, y, n = *_n;

    for (y = 0; y < ROWS_NUM; y++)
        for (x = 0; x < COLS_NUM; x++)
        {
            GetWord(&words[n], x, y, dx, dy);
            word_ptrs[n] = &words[n];
            n++;
        }
    *_n = n;
}

I64 WordsCompare(U8 *e1, U8 *e2)
{
    return StrCompare(e1, e2);
}

/*Format of word list entry:
    U8 ACD_WORD_CHAR
    U8 word[] with terminating zero
    I16 block; //definition offset in ::/System/AutoComplete/ACDefs.DATA
*/

U0 DisplayWords(I64 n)
{
    I64 i = 0, k;
    U8 *w1, *w2, *dict = acd.word_list;

    for (i = 0; i < n; i++)
        while (*dict)
        {
            w1 = word_ptrs[i];
            w2 = dict + 1;
            while (*w2 && *w1 == ToUpper(*w2))
            {
                w1++;
                w2++;
            }
            if (ToUpper(*w2) > *w1)
                break;
            if (!*w2)
            {
                if (StrLen(dict + 1) > 2)
                {
                    k = i;
                    while (k < n && !StrNICompare(word_ptrs[k++], dict + 1, StrLen(dict + 1)))
                        "%s ", dict + 1;
                }
                w2 = dict + 1;
                while (!StrICompare(w2, dict + 1))
                    dict += StrLen(dict + 1) + 4;
            }
            else
                dict += StrLen(dict + 1) + 4;
        }
}

U0 FancyWordSearch()
{
    I64 n = 0;

    CollectWords( 1,  0, &n);
    CollectWords( 0,  1, &n);
    CollectWords(-1,  0, &n);
    CollectWords( 0, -1, &n);
    CollectWords( 1,  1, &n);
    CollectWords(-1, -1, &n);
    CollectWords( 1, -1, &n);
    CollectWords(-1,  1, &n);
    QuickSortI64(word_ptrs, n, &WordsCompare);
    DisplayWords(n);
    '\n';
}

//************************************
U0 WordSearch()
{
    Init;
    Display;
    '\n';
    SimpleWordSearch;
    FancyWordSearch;
}

WordSearch;