/* * These functions do the pop-up pull-down command menus. * * Being stupid, I can't remember what half the function keys do. * Fortunately, it is very easy to write a pop-up pull-down command menu * to run editor commands. Being lazy, I didn't implement CUA style menus, * because we can provide most of the CUA benefits with a single hot-key. * Also, dumb UNIX terminals don't have a lot function keys to spare. * * New editor name: TDE, the Thomson-Davis Editor. * Author: Frank Davis * Date: June 5, 1991, version 1.0 * Date: July 29, 1991, version 1.1 * Date: October 5, 1991, version 1.2 * Date: January 20, 1992, version 1.3 * Date: February 17, 1992, version 1.4 * Date: April 1, 1992, version 1.5 * Date: June 5, 1992, version 2.0 * Date: October 31, 1992, version 2.1 * Date: April 1, 1993, version 2.2 * Date: June 5, 1993, version 3.0 * Date: August 29, 1993, version 3.1 * Date: November 13, 1993, version 3.2 * Date: June 5, 1994, version 4.0 * * This code is released into the public domain, Frank Davis. * You may distribute it freely. */ #include "tdestr.h" #include "common.h" #include "define.h" #include "tdefunc.h" static int saved_major = 0; static int saved_minor = 0; /* * Name: main_pull_down * Purpose: show pull down menu and call function if needed * Date: November 13, 1993 * Passed: window: current window * Notes: keep a record of the last menu choice in local global variables. */ int main_pull_down( TDE_WIN *window ) { int rc; int ch; int row; int major_choice; int minor_choice; #if defined( __UNIX__ ) chtype display_buff[MAX_COLS+2]; /* chtype is defined in curses.h */ #else char display_buff[(MAX_COLS+2)*2]; #endif rc = ERROR; row = 0; major_choice = saved_major; minor_choice = saved_minor; save_screen_line( 0, row, display_buff ); ch = lite_bar_menu( &major_choice, &minor_choice ); restore_screen_line( 0, row, display_buff ); saved_major = major_choice; saved_minor = minor_choice; if (ch == Rturn) { g_status.command = menu[major_choice].minor[minor_choice].minor_func; g_status.control_break = FALSE; if (g_status.command >= 0 && g_status.command < NUM_FUNCS) rc = (*do_it[g_status.command])( window ); else rc = ERROR; } return( rc ); } /* * Name: lite_bar_menu * Purpose: handle major menu choices * Date: November 13, 1993 * Passed: maj: pointer to menu bar choice * min: pointer to function under menu * Returns: last key pressed * Notes: set the menu structures */ int lite_bar_menu( int *maj, int *min ) { int major_col[MAJOR]; int major_width[MAJOR]; int col; int row; int wid; int ch; char blanks[MAX_COLS+2]; /* * put the pull-down menu on the first line of screen. */ col = row = 0; memset( blanks, ' ', g_display.ncols ); blanks[g_display.ncols] = '\0'; s_output( blanks, row, col, g_display.head_color ); get_bar_spacing( col+1, major_col, major_width ); draw_lite_head( row, major_col ); xygoto( -1, -1 ); get_minor_counts( ); ch = -1; while (ch != AbortCommand && ch != Rturn) { if (ch == CharRight) { hlight_line( major_col[*maj], row, major_width[*maj], g_display.mode_color ); ++*maj; if (*maj >= MAJOR) *maj = 0; *min = 0; ch = -1; } else if (ch == CharLeft) { hlight_line( major_col[*maj], row, major_width[*maj], g_display.mode_color ); --*maj; if (*maj < 0) *maj = MAJOR - 1; *min = 0; ch = -1; } hlight_line( major_col[*maj], row, major_width[*maj], g_display.block_color ); #if defined( __UNIX__ ) refresh( ); #endif col = major_col[*maj]; wid = strlen( menu[*maj].minor[0].minor_name ); if (col + wid + 2 > g_display.ncols - 1) col = g_display.ncols - 1 - wid; *min = pull_me( *maj, *min, row+1, col, &ch ); } return( ch ); } /* * Name: pull_me * Purpose: move cursor up and down the menu bar * Date: November 13, 1993 * Passed: maj: main menu bar choice * min: subfunction choice * row: row to begin vertical choice * col: column to begin vertical choice * ch: pointer to current key * Returns: last key pressed * Notes: save the text under the pulled down menu */ int pull_me( int maj, int min, int row, int col, int *ch ) { int i; int minor_width; int cnt; int select; int begin; int end; #if defined( __UNIX__ ) chtype *buffer; #else int *buffer; #endif cnt = menu[maj].minor_cnt; /* * find first valid minor selection. */ for (begin=0; menu[maj].minor[begin].minor_func < 0; begin++); /* * find last valid minor selection */ for (end=cnt-1; menu[maj].minor[end].minor_func < 0; end--); minor_width = strlen( menu[maj].minor[0].minor_name ); select = min; if (menu[maj].minor[select].minor_func < 0) { select = begin; while (menu[maj].minor[select].minor_func < 0) ++select; } #if defined( __UNIX__ ) buffer = (chtype *)malloc( minor_width * cnt * sizeof(chtype) ); #else buffer = (int *)malloc( minor_width * cnt * sizeof(int) ); #endif if (buffer != NULL) { save_minor_area( buffer, minor_width, cnt, row, col ); for (i=0; i< cnt; i++) s_output( menu[maj].minor[i].minor_name, row+i, col, g_display.help_color ); hlight_line( col+1, row+select, minor_width-2, g_display.hilited_file ); while (*ch != AbortCommand && *ch != CharRight && *ch != CharLeft && *ch != Rturn) { if (*ch == LineDown) { hlight_line( col+1, row+select, minor_width-2, g_display.help_color ); ++select; while (menu[maj].minor[select].minor_func < 0) ++select; if (select >= cnt) select = begin; hlight_line( col+1, row+select, minor_width-2, g_display.hilited_file ); } else if (*ch == LineUp) { hlight_line( col+1, row+select, minor_width-2, g_display.help_color ); --select; while (menu[maj].minor[select].minor_func < 0) --select; if (select < 0) select = end; hlight_line( col+1, row+select, minor_width-2, g_display.hilited_file ); } #if defined( __UNIX__ ) refresh( ); #endif *ch = getkey( ); *ch = getfunc( *ch ); if (*ch == ESC) *ch = AbortCommand; } restore_minor_area( buffer, minor_width, cnt, row, col ); free( buffer ); } else { select = -1; *ch = AbortCommand; } return( select ); } /* * Name: get_bar_spacing * Purpose: calculate headings for main menu choices * Date: November 13, 1993 * Passed: col: col of first menu choice * major_col: column to display each menu heading * major_width: width of each menu heading * Notes: assume 6 spaces between the menu items */ void get_bar_spacing( int col, int major_col[], int major_width[] ) { int i, j; for (i=j=0; i< MAJOR; i++) { major_col[i] = col+j; major_width[i] = strlen( menu[i].major_name ); j += major_width[i] + 6; } } /* * Name: draw_lite_head * Purpose: slap the main menu choices on the lite bar * Date: November 13, 1993 * Passed: row: lite bar row * major_col: column to display each menu heading */ void draw_lite_head( int row, int major_col[] ) { int i; for (i=0; i< MAJOR; i++) s_output( menu[i].major_name, row, major_col[i], g_display.mode_color ); #if defined( __UNIX__ ) refresh( ); #endif } /* * Name: get_minor_counts * Purpose: find number of items under each main menu * Date: November 13, 1993 */ void get_minor_counts( void ) { int i; int cnt; for (i=0; i