home *** CD-ROM | disk | FTP | other *** search
- /*======================================================*/
- /* UIMBUILD.C */
- /* */
- /* (c) Copyright 1988 Ralf Brown. All Rights Reserved. */
- /*======================================================*/
-
- #include <mem.h>
- #include <string.h>
- #include "tvapi.h"
- #include "tvstream.h"
- #include "tvui.h"
-
- /*======================================================*/
- /*======================================================*/
-
- #define physical_screen_height() ((*(BYTE far *)0x00400084L)+1)
- #define physical_screen_width() (*(int far *)0x0040004AL)
- #define PRIVATE(type) static type near pascal
-
- #define HEADER_SIZE 4
-
- /*======================================================*/
- /*======================================================*/
-
- static BYTE fixed_stream_header[] =
- {
- S_WINDOW(0), /* will fill in length later */
- WS_HIDDEN, /* hide until we finish our setup */
- WS_LSIZE(0,0), /* will fill in logical size later */
- WS_WINPOS(0,0), /* will fill in window position later */
- WS_WINSIZE(0,0), /* will fill in window size later */
- WS_NOFRAME, /* we don't want a frame */
- WS_LOGATTR, /* we want logical attributes */
- WS_WRITEATTR, /* change attributes when writing */
- WS_NOCTRLCHAR,
- WS_SETCOLOR(1), /* use normal attribute */
- WS_CLEAR, /* and clear screen to that color */
- WS_SETCOLOR(3), /* change to border color */
- WS_CURSPOS(0,1), /* home cursor */
- WS_MANYCHAR(0,223), /* write top edge of border, fill in count later */
- WS_SETCURSCOL(0), /* back to left edge */
- WS_REPEAT(0), /* will fill in count later */
- WS_CHARS(1),222, /* write left edge of border */
- WS_SETCURSCOL(0), /* fill in later, moves to right edge */
- WS_CHARS(1),221, /* write right edge of border */
- WS_DOREPEAT,
- WS_CURSPOS(0,1), /* fill in row later */
- WS_MANYCHAR(0,220), /* write bottom edge of border, fill in count later */
- WS_SETCOLOR(9), /* reverse video for title */
- WS_SETCURSROW(1),
- WS_SETCURSCOL(0), /* fill in column later */
- WS_MANYCHARS(0), /* fill in count later */
- /* rest of stream must be built at runtime */
- } ;
-
- static BYTE fixed_stream_trailer[] = {
- WS_FLDCURS(1),
- WS_UPDATE,
- S_MANAGER(9), 0xBD, /* enable one of DESQview's extensions, don't know which */
- MS_CURRFLDPOS, 0, 0,
- MS_DISALLOW | TV_HMOVE,
- MS_DISALLOW | TV_VMOVE,
- MS_WINTOP, MS_FLDMARKER(0xAF) /* default field marker is ยป */
- } ;
-
- /*======================================================*/
- /*======================================================*/
-
- void * pascal UImenu_build(MENU_ITEM *menu_items,MENU_OPTIONS *menu_options)
- {
- register int tmp ;
- int stream_size ;
- BYTE *stream_start, *stream ;
- int two_keys = FALSE ;
- int phys_width = physical_screen_width() ;
- int phys_height = physical_screen_height() ;
- int num_fields = 0 ;
- MENU_ITEM *menu_item ;
- int width = 0 ;
- int height = 4 ; /* top & bottom edges + title + key echo area */
- int overhead ; /* how much space we need for menu's keystrokes */
- int row, col ;
- int line ;
-
- /* find out whether we'll need one space or two for the menu's keystrokes */
-
- for (menu_item = menu_items ; menu_item->type != M_END ; menu_item++)
- if ((menu_item->type == M_ITEM || menu_item->type == M_SPECIAL) &&
- menu_item->key2 != 0)
- {
- two_keys = TRUE ;
- break ;
- }
- overhead = (two_keys ? 4 : 3) ;
-
- /* determine how much memory to allocate for the stream, and simultaneously */
- /* how big the menu window will be */
-
- stream_size = sizeof( fixed_stream_header ) +
- sizeof( fixed_stream_trailer ) +
- strlen(menu_options->title) + sizeof(FT_HEADER) + 7 ;
- for (menu_item = menu_items ; menu_item->type != M_END ; menu_item++)
- {
- switch (menu_item->type)
- {
- case M_ITEM:
- if (menu_item->entry == NULL || *menu_item->entry == '\0')
- return ME_BADITEM ;
- tmp = strlen(menu_item->entry) ;
- stream_size += tmp + ((two_keys && menu_item->key2 != 0) ? 11 : 10) ;
- num_fields++ ;
- if (tmp + overhead > width)
- width = tmp + overhead ;
- break ;
- case M_HTEXT:
- case M_TEXT:
- stream_size += 4 ;
- if (menu_item->entry && strlen(menu_item->entry) > 0)
- {
- tmp = strlen(menu_item->entry) ;
- stream_size += tmp + ((menu_item->type == M_HTEXT) ? 6 : 2) ;
- if (tmp > width)
- width = tmp ;
- }
- break ;
- case M_CENTER:
- case M_HCENTER:
- stream_size += 2 ;
- if (menu_item->entry && strlen(menu_item->entry) > 0)
- {
- tmp = strlen(menu_item->entry) ;
- stream_size += tmp + ((menu_item->type == M_HCENTER) ? 8 : 4) ;
- if (tmp > width)
- width = tmp ;
- }
- break ;
- case M_SEP:
- stream_size += 7 ;
- break ;
- case M_SPECIAL:
- if (menu_item->entry == NULL || strchr(menu_item->entry,' ') == NULL)
- return ME_BADITEM ;
- tmp = strlen(menu_item->entry) ;
- stream_size += tmp + 10 ;
- num_fields++ ;
- if (tmp > width)
- width = tmp ;
- break ;
- case M_IGNORE:
- /* do nothing */
- break ;
- default:
- return ME_BADITEM ; /* indicate error */
- }
- if (menu_item->type != M_IGNORE)
- height++ ;
- }
- stream_size += num_fields*sizeof(FT_ENTRY) ;
- if (two_keys)
- stream_size += sizeof(FT_ENTRY) ;
- if (strlen(menu_options->title) > width)
- width = strlen(menu_options->title) ;
- width += 4 ; /* left & right edge, blanks just inside edges */
-
- /* perform some simple error checks before proceeding */
-
- if (height > phys_height || width > phys_width)
- return ME_TOOBIG ;
- if ((stream_start = (BYTE *)malloc(stream_size+HEADER_SIZE)) == NULL)
- return ME_NOMEM ;
-
- /* determine upper left corner of menu window */
-
- if (menu_options->row < 0)
- {
- row = phys_height - height + menu_options->row + 1 ;
- if (row < 0)
- row = 0 ;
- }
- else
- {
- row = menu_options->row ;
- if (row + height > phys_height)
- row = phys_height - height ;
- }
- if (menu_options->col < 0)
- {
- col = phys_width - width + menu_options->col + 1 ;
- if (col < 0)
- col = 0 ;
- }
- else
- {
- col = menu_options->col ;
- if (col + width > phys_width)
- col = phys_width - width ;
- }
-
- /* start building the stream */
-
- stream = stream_start ;
- *((int *)stream)++ = stream_size ;
- *((int *)stream)++ = num_fields ;
- memcpy( stream, fixed_stream_header, sizeof( fixed_stream_header ) ) ;
- *((int *)(stream+2)) = stream_size - sizeof( fixed_stream_trailer ) ;
- stream[HEADER_SIZE+2] = height ;
- stream[HEADER_SIZE+3] = width ;
- stream[HEADER_SIZE+5] = row ;
- stream[HEADER_SIZE+6] = col ;
- stream[HEADER_SIZE+8] = height ;
- stream[HEADER_SIZE+9] = width ;
- stream[HEADER_SIZE+23] = width-2 ;
- stream[HEADER_SIZE+28] = height ;
- stream[HEADER_SIZE+32] = width-1 ;
- stream[HEADER_SIZE+37] = height-1 ;
- stream[HEADER_SIZE+40] = width-2 ;
- stream += sizeof( fixed_stream_header ) ;
- tmp = strlen(menu_options->title) ;
- stream[-1] = tmp ;
- stream[-3] = (width-tmp)/2 ;
- memcpy( stream, menu_options->title, tmp ) ;
- stream += tmp ;
- *((int *)stream)++ = 0x01E2 ; /* set color back to normal */
- *((int *)stream)++ = 0x02A0 ; /* skip next line */
- for (menu_item = menu_items ; menu_item->type != M_END ; menu_item++)
- if (menu_item->type != M_IGNORE)
- {
- *((int *)stream)++ = 0x01B0 ; /* move to start of next line */
- switch (menu_item->type)
- {
- case M_ITEM:
- *((int *)stream)++ = 0x02A1 ; /* leave a blank at start of line */
- *stream++ = 0x98 ;
- *stream++ = tmp = strlen(menu_item->entry) ;
- memcpy((char *)stream,menu_item->entry,tmp) ;
- stream += tmp ;
- *stream++ = 0xB1 ;
- *stream++ = width - tmp - (two_keys ? 6 : 5 ) ;
- if (two_keys)
- {
- *stream++ = (menu_item->key2) ? 0x62 : 0x61 ;
- *stream++ = (menu_item->key1) ? menu_item->key1 : ' ' ;
- if (menu_item->key2)
- *stream++ = menu_item->key2 ;
- }
- else
- {
- *stream++ = 0x61 ;
- *stream++ = (menu_item->key1) ? menu_item->key1 : ' ' ;
- }
- break ;
- case M_TEXT:
- case M_HTEXT:
- *((int *)stream)++ = 0x02A1 ; /* leave a blank at start of line */
- if (menu_item->entry && (tmp = strlen(menu_item->entry)) > 0)
- {
- if (menu_item->type == M_HTEXT)
- *((int *)stream)++ = 0x02E2 ; /* change to highlighted */
- *stream++ = 0x98 ;
- *stream++ = tmp ;
- memcpy(stream,menu_item->entry,tmp) ;
- stream += tmp ;
- if (menu_item->type == M_HTEXT)
- *((int *)stream)++ = 0x01E2 ; /* change back to normal */
- }
- break ;
- case M_CENTER:
- case M_HCENTER:
- if (menu_item->entry && *menu_item->entry)
- {
- if (menu_item->type == M_HCENTER)
- *((int *)stream)++ = 0x02E2 ; /* change to highlighted */
- tmp = strlen(menu_item->entry) ;
- *stream++ = 0xA1 ;
- *stream++ = (width - tmp) / 2 ;
- *stream++ = 0x98 ;
- *stream++ = tmp ;
- memcpy(stream,menu_item->entry,tmp) ;
- stream += tmp ;
- if (menu_item->type == M_HCENTER)
- *((int *)stream)++ = 0x01E2 ; /* change back to normal */
- }
- break ;
- case M_SEP:
- *((int *)stream)++ = 0x01A1 ; /* don't leave a blank at start of line */
- *stream++ = 0x88 ; /* replicate key across line */
- *stream++ = width-2 ;
- *stream++ = menu_item->key1 ;
- break ;
- case M_SPECIAL:
- {
- char *keyname = strrchr( menu_item->entry, ' ' ) + 1 ;
-
- *((int *)stream)++ = 0x02A1 ; /* leave a blank at start of line */
- *stream++ = 0x98 ;
- *stream++ = tmp = keyname - menu_item->entry ;
- memcpy( stream, menu_item->entry, tmp ) ;
- stream += tmp ;
- *stream++ = 0xB1 ; /* skip over to end of line */
- *stream++ = width - 4 - tmp - strlen(keyname) ;
- *stream++ = 0x98 ; /* show key to press */
- *stream++ = tmp = strlen(keyname) ;
- memcpy( stream, keyname, tmp ) ;
- stream += tmp ;
- }
- break ;
- }
- }
- *((int *)stream)++ = 0x18E5 ;
- *stream++ = 0xFF ;
- if (two_keys)
- *stream++ = ((int *)stream_start)[1] + 1 ;
- else
- *stream++ = ((int *)stream_start)[1] ;
- tmp = F_READARRAY ;
- if (menu_options->allow_kbd)
- tmp |= F_ALLOWKBD ;
- if (menu_options->left_button)
- tmp |= F_LEFTBUTTON ;
- if (menu_options->right_button)
- tmp |= F_RIGHTBUTTON ;
- *stream++ = tmp ;
- *((int *)stream)++ = 0 ;
- *((int *)stream)++ = 0x0209 ;
- menu_item = menu_items ;
- line = 3 ;
- while (menu_item->type != M_END)
- {
- if (menu_item->type == M_ITEM || menu_item->type == M_SPECIAL)
- {
- *stream++ = line ;
- *stream++ = 1 ;
- *stream++ = line ;
- *stream++ = width-2 ;
- *stream++ = (menu_item->selected) ? 0xC0 : 0xC0 | F_SELECTED ;
- *stream++ = menu_item->key1 ;
- *stream++ = 1 ;
- *stream++ = two_keys ? menu_item->key2 : 0 ;
- }
- if (menu_item->type != M_IGNORE)
- line++ ;
- menu_item++ ;
- }
- if (two_keys)
- {
- *stream++ = 2 ;
- *stream++ = (width+1)/2-1 ;
- *stream++ = 2 ;
- *stream++ = (width+1)/2-1 ;
- *stream++ = 0x40 ;
- *stream++ = 0 ;
- *stream++ = 0 ;
- *stream++ = 0 ;
- }
- memcpy( stream, fixed_stream_trailer, sizeof( fixed_stream_trailer )) ;
- if (menu_options->marker)
- stream[sizeof(fixed_stream_trailer)-1] = menu_options->marker ;
- return (void *) stream_start ;
- }
-
- /* End of UIMBUILD.C */
-